diff --git a/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/EdcRuntimeExtension.java b/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/EdcRuntimeExtension.java index cce2625a6e5..9efdb32b039 100644 --- a/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/EdcRuntimeExtension.java +++ b/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/EdcRuntimeExtension.java @@ -33,6 +33,7 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import static java.lang.String.format; @@ -113,8 +114,8 @@ public void beforeTestExecution(ExtensionContext extensionContext) throws Except var savedProperties = (Properties) System.getProperties().clone(); properties.forEach(System::setProperty); + var runtimeException = new AtomicReference(); var latch = new CountDownLatch(1); - runtimeThread = new Thread(() -> { try { @@ -127,6 +128,7 @@ public void beforeTestExecution(ExtensionContext extensionContext) throws Except latch.countDown(); } catch (Exception e) { + runtimeException.set(e); throw new EdcException(e); } }); @@ -136,7 +138,7 @@ public void beforeTestExecution(ExtensionContext extensionContext) throws Except runtimeThread.start(); if (!latch.await(20, SECONDS)) { - throw new EdcException("Failed to start EDC runtime"); + throw new EdcException("Failed to start EDC runtime", runtimeException.get()); } MONITOR.info("Runtime %s started".formatted(name)); diff --git a/core/common/lib/transform-lib/build.gradle.kts b/core/common/lib/transform-lib/build.gradle.kts index 919d94af51f..d2c0d1d4a41 100644 --- a/core/common/lib/transform-lib/build.gradle.kts +++ b/core/common/lib/transform-lib/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { api(project(":spi:common:core-spi")) api(project(":spi:common:json-ld-spi")) api(project(":spi:common:transform-spi")) + api(project(":spi:data-plane-selector:data-plane-selector-spi")) api(libs.jakartaJson) diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectFromDataPlaneInstanceTransformer.java b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataPlaneInstanceTransformer.java similarity index 98% rename from extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectFromDataPlaneInstanceTransformer.java rename to core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataPlaneInstanceTransformer.java index 98b1319a2b2..35fd2540d50 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectFromDataPlaneInstanceTransformer.java +++ b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataPlaneInstanceTransformer.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.connector.dataplane.selector.transformer; +package org.eclipse.edc.transform.transformer.edc.from; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.JsonBuilderFactory; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectToDataPlaneInstanceTransformer.java b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataPlaneInstanceTransformer.java similarity index 98% rename from extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectToDataPlaneInstanceTransformer.java rename to core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataPlaneInstanceTransformer.java index b1de23c3a1a..1ed64ca919f 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectToDataPlaneInstanceTransformer.java +++ b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataPlaneInstanceTransformer.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.connector.dataplane.selector.transformer; +package org.eclipse.edc.transform.transformer.edc.to; import jakarta.json.JsonArray; import jakarta.json.JsonNumber; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectFromDataPlaneInstanceTransformerTest.java b/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataPlaneInstanceTransformerTest.java similarity index 98% rename from extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectFromDataPlaneInstanceTransformerTest.java rename to core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataPlaneInstanceTransformerTest.java index 26e6225c27e..4250b3752aa 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectFromDataPlaneInstanceTransformerTest.java +++ b/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataPlaneInstanceTransformerTest.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.connector.dataplane.selector.transformer; +package org.eclipse.edc.transform.transformer.edc.from; import jakarta.json.Json; import jakarta.json.JsonString; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectToDataPlaneInstanceTransformerTest.java b/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataPlaneInstanceTransformerTest.java similarity index 99% rename from extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectToDataPlaneInstanceTransformerTest.java rename to core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataPlaneInstanceTransformerTest.java index cd9e42d3862..d9c51446d8d 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/transformer/JsonObjectToDataPlaneInstanceTransformerTest.java +++ b/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataPlaneInstanceTransformerTest.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.edc.connector.dataplane.selector.transformer; +package org.eclipse.edc.transform.transformer.edc.to; import jakarta.json.Json; import jakarta.json.JsonObject; diff --git a/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImpl.java b/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImpl.java index 87579b33d55..df0ffd48593 100644 --- a/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImpl.java +++ b/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImpl.java @@ -39,7 +39,6 @@ import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.telemetry.Telemetry; -import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.edc.transaction.spi.TransactionContext; import org.eclipse.edc.validator.spi.DataAddressValidatorRegistry; @@ -52,7 +51,6 @@ import static java.lang.String.format; import static java.util.UUID.randomUUID; import static java.util.stream.Collectors.joining; -import static org.eclipse.edc.connector.controlplane.transfer.dataplane.spi.TransferDataPlaneConstants.HTTP_PROXY; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess.Type.CONSUMER; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess.Type.PROVIDER; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.SUSPENDED; @@ -153,9 +151,6 @@ public ServiceResult findById(String id, TokenRepresentation to @NotNull private ServiceResult requestedAction(TransferRequestMessage message, String assetId) { - var destination = message.getDataDestination() != null - ? message.getDataDestination() : DataAddress.Builder.newInstance().type(HTTP_PROXY).build(); - var existingTransferProcess = transferProcessStore.findForCorrelationId(message.getConsumerPid()); if (existingTransferProcess != null) { return ServiceResult.success(existingTransferProcess); @@ -165,7 +160,7 @@ private ServiceResult requestedAction(TransferRequestMessage me .protocol(message.getProtocol()) .correlationId(message.getConsumerPid()) .counterPartyAddress(message.getCallbackAddress()) - .dataDestination(destination) + .dataDestination(message.getDataDestination()) .assetId(assetId) .contractId(message.getContractId()) .transferType(message.getTransferType()) diff --git a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImplTest.java b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImplTest.java index 435da14d375..c2dc3cc1683 100644 --- a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImplTest.java +++ b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessProtocolServiceImplTest.java @@ -65,7 +65,6 @@ import static java.util.Collections.emptyMap; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.connector.controlplane.services.transferprocess.TransferProcessProtocolServiceImpl.TRANSFER_PROCESS_REQUEST_SCOPE; -import static org.eclipse.edc.connector.controlplane.transfer.dataplane.spi.TransferDataPlaneConstants.HTTP_PROXY; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess.Type.CONSUMER; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess.Type.PROVIDER; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.COMPLETED; @@ -223,36 +222,6 @@ void notifyRequested_invalidDestination_shouldNotInitiateTransfer() { verifyNoInteractions(listener); } - @Test - void notifyRequested_missingDestination_shouldInitiateTransfer() { - var participantAgent = participantAgent(); - var tokenRepresentation = tokenRepresentation(); - var message = TransferRequestMessage.Builder.newInstance() - .consumerPid("consumerPid") - .processId("consumerPid") - .protocol("protocol") - .contractId("agreementId") - .callbackAddress("http://any") - .build(); - - when(protocolTokenValidator.verify(eq(tokenRepresentation), eq(TRANSFER_PROCESS_REQUEST_SCOPE), any(), eq(message))).thenReturn(ServiceResult.success(participantAgent)); - when(negotiationStore.findContractAgreement(any())).thenReturn(contractAgreement()); - when(validationService.validateAgreement(any(ParticipantAgent.class), any())).thenReturn(Result.success(null)); - - var result = service.notifyRequested(message, tokenRepresentation); - - assertThat(result).isSucceeded().satisfies(transferProcess -> { - assertThat(transferProcess.getCorrelationId()).isEqualTo("consumerPid"); - assertThat(transferProcess.getCounterPartyAddress()).isEqualTo("http://any"); - assertThat(transferProcess.getAssetId()).isEqualTo("assetId"); - assertThat(transferProcess.getDataDestination().getType()).isEqualTo(HTTP_PROXY); - }); - verify(listener).preCreated(any()); - verify(store).save(argThat(t -> t.getState() == INITIAL.code())); - verify(listener).initiated(any()); - verify(transactionContext, atLeastOnce()).execute(any(TransactionContext.ResultTransactionBlock.class)); - } - @Test void notifyCompleted_shouldTransitionToCompleted() { var participantAgent = participantAgent(); diff --git a/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorService.java b/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorService.java index da6505d6635..8ddf0dc7f53 100644 --- a/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorService.java +++ b/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorService.java @@ -24,6 +24,7 @@ import org.eclipse.edc.transaction.spi.TransactionContext; import java.util.List; +import java.util.Optional; public class EmbeddedDataPlaneSelectorService implements DataPlaneSelectorService { @@ -48,14 +49,15 @@ public List getAll() { @Override public DataPlaneInstance select(DataAddress source, DataAddress destination, String selectionStrategy, String transferType) { - var strategy = selectionStrategyRegistry.find(selectionStrategy); + var sanitizedSelectionStrategy = Optional.ofNullable(selectionStrategy).orElse(DEFAULT_STRATEGY); + var strategy = selectionStrategyRegistry.find(sanitizedSelectionStrategy); if (strategy == null) { - throw new IllegalArgumentException("Strategy " + selectionStrategy + " was not found"); + throw new IllegalArgumentException("Strategy " + sanitizedSelectionStrategy + " was not found"); } return transactionContext.execute(() -> { try (var stream = store.getAll()) { - var dataPlanes = stream.filter(dataPlane -> dataPlane.canHandle(source, destination, transferType)).toList(); + var dataPlanes = stream.filter(dataPlane -> dataPlane.canHandle(source, transferType)).toList(); return strategy.apply(dataPlanes); } }); diff --git a/core/data-plane-selector/data-plane-selector-core/src/test/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorServiceTest.java b/core/data-plane-selector/data-plane-selector-core/src/test/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorServiceTest.java index 3264a65b142..029dcabaa1d 100644 --- a/core/data-plane-selector/data-plane-selector-core/src/test/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorServiceTest.java +++ b/core/data-plane-selector/data-plane-selector-core/src/test/java/org/eclipse/edc/connector/dataplane/selector/service/EmbeddedDataPlaneSelectorServiceTest.java @@ -46,7 +46,7 @@ void select_shouldUseChosenSelector() { when(selectionStrategy.apply(any())).thenAnswer(it -> instances.get(0)); when(selectionStrategyRegistry.find(any())).thenReturn(selectionStrategy); - var result = selector.select(createAddress("srcTestType"), createAddress("destTestType"), "strategy"); + var result = selector.select(createAddress("srcTestType"), createAddress("destTestType"), "strategy", "transferType"); assertThat(result).isNotNull().extracting(DataPlaneInstance::getId).isEqualTo("instance0"); verify(selectionStrategyRegistry).find("strategy"); @@ -58,7 +58,7 @@ void select_shouldThrowException_whenStrategyNotFound() { when(store.getAll()).thenReturn(instances.stream()); when(selectionStrategyRegistry.find(any())).thenReturn(null); - assertThatThrownBy(() -> selector.select(createAddress("srcTestType"), createAddress("destTestType"), "strategy")) + assertThatThrownBy(() -> selector.select(createAddress("srcTestType"), createAddress("destTestType"), "strategy", "transferType")) .isInstanceOf(IllegalArgumentException.class); } diff --git a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImpl.java b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImpl.java index c7668c8dfd4..8bfe756ccd8 100644 --- a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImpl.java +++ b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImpl.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -43,4 +44,9 @@ public Result generateFor(DataAddress sourceDataAddress) { public void addGeneratorFunction(String destinationType, Function generatorFunction) { generatorFunctions.put(destinationType, generatorFunction); } + + @Override + public Set supportedDestinationTypes() { + return generatorFunctions.keySet(); + } } diff --git a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImpl.java b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImpl.java index e421228abd0..192ab969b30 100644 --- a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImpl.java +++ b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImpl.java @@ -33,10 +33,12 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.CompletableFuture; import static java.lang.String.format; import static java.util.concurrent.CompletableFuture.completedFuture; +import static java.util.stream.Collectors.toSet; /** * Default pipeline service implementation. @@ -140,6 +142,16 @@ public void registerFactory(DataSinkFactory factory) { sinkFactories.add(factory); } + @Override + public Set supportedSourceTypes() { + return sourceFactories.stream().map(DataSourceFactory::supportedType).collect(toSet()); + } + + @Override + public Set supportedSinkTypes() { + return sinkFactories.stream().map(DataSinkFactory::supportedType).collect(toSet()); + } + @Nullable private DataSourceFactory getSourceFactory(DataFlowStartMessage request) { return sourceFactories.stream() diff --git a/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImplTest.java b/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImplTest.java index ac96773410b..28894c9da9e 100644 --- a/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImplTest.java +++ b/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/PublicEndpointGeneratorServiceImplTest.java @@ -18,6 +18,7 @@ import org.eclipse.edc.spi.types.domain.DataAddress; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; @@ -42,4 +43,12 @@ void generateFor_noFunction() { .isEqualTo("No Endpoint generator function registered for source data type 'testtype'"); } -} \ No newline at end of file + @Test + void supportedTypes() { + generatorService.addGeneratorFunction("type", dataAddress -> new Endpoint("any", "any")); + + var result = generatorService.supportedDestinationTypes(); + + assertThat(result).containsOnly("type"); + } +} diff --git a/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImplTest.java b/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImplTest.java index ffe0779360d..4bf4f70d055 100644 --- a/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImplTest.java +++ b/core/data-plane/data-plane-core/src/test/java/org/eclipse/edc/connector/dataplane/framework/pipeline/PipelineServiceImplTest.java @@ -24,6 +24,7 @@ import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.domain.DataAddress; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; @@ -160,6 +161,31 @@ void canHandle_shouldReturnTrue_whenSourceAndDestinationCanBeHandled(String sour assertThat(result).isEqualTo(expected); } + @Nested + class SupportedTypes { + + @Test + void shouldReturnSourceTypesFromFactories() { + when(sourceFactory.supportedType()).thenReturn("source"); + + var result = service.supportedSourceTypes(); + + assertThat(result).containsOnly("source"); + verifyNoInteractions(sinkFactory); + } + + @Test + void shouldReturnSinkTypesFromFactories() { + when(sinkFactory.supportedType()).thenReturn("sink"); + + var result = service.supportedSinkTypes(); + + assertThat(result).containsOnly("sink"); + verifyNoInteractions(sourceFactory); + } + + } + private DataFlow dataFlow(String sourceType, String destinationType) { return DataFlow.Builder.newInstance() .id("1") diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/build.gradle.kts b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/build.gradle.kts index bcc290608ef..70f6d4d21d9 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/build.gradle.kts +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/build.gradle.kts b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/build.gradle.kts index 53e9e92124f..5fc848c9307 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/build.gradle.kts +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/build.gradle.kts b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/build.gradle.kts index a4367be27fa..15a263764c7 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/build.gradle.kts +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/data-protocols/dsp/dsp-version/dsp-version-http-api/build.gradle.kts b/data-protocols/dsp/dsp-version/dsp-version-http-api/build.gradle.kts index f18879fa717..084251fd86e 100644 --- a/data-protocols/dsp/dsp-version/dsp-version-http-api/build.gradle.kts +++ b/data-protocols/dsp/dsp-version/dsp-version-http-api/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { @@ -34,4 +34,4 @@ edcBuild { swagger { apiGroup.set("dsp-api") } -} \ No newline at end of file +} diff --git a/docs/developer/openapi.md b/docs/developer/openapi.md index eaf259491e7..28313e4643f 100644 --- a/docs/developer/openapi.md +++ b/docs/developer/openapi.md @@ -33,7 +33,7 @@ val rsApi: String by project plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") //<-- add this + id(libs.plugins.swagger.get().pluginId) //<-- add this } dependencies { @@ -55,7 +55,7 @@ add your module to one of the categories, simply add this block to your module's ```kotlin plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/common/api/api-observability/build.gradle.kts b/extensions/common/api/api-observability/build.gradle.kts index 390d519ff32..7803c9d936e 100644 --- a/extensions/common/api/api-observability/build.gradle.kts +++ b/extensions/common/api/api-observability/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/common/api/control-api-configuration/build.gradle.kts b/extensions/common/api/control-api-configuration/build.gradle.kts index 2bb83ff6a09..06aaa4dd05d 100644 --- a/extensions/common/api/control-api-configuration/build.gradle.kts +++ b/extensions/common/api/control-api-configuration/build.gradle.kts @@ -18,8 +18,9 @@ plugins { } dependencies { - implementation(project(":extensions:common:api:api-core")) api(project(":spi:control-plane:transfer-spi")) + implementation(project(":extensions:common:api:api-core")) + implementation(project(":extensions:common:http:lib:jersey-providers-lib")) testImplementation(project(":core:common:junit")) } diff --git a/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java b/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java index af8a44af242..7eb413d81a9 100644 --- a/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java +++ b/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java @@ -15,6 +15,7 @@ package org.eclipse.edc.connector.api.control.configuration; import org.eclipse.edc.connector.controlplane.transfer.spi.callback.ControlApiUrl; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provides; @@ -23,7 +24,11 @@ import org.eclipse.edc.spi.system.Hostname; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.edc.web.jersey.providers.jsonld.JerseyJsonLdInterceptor; +import org.eclipse.edc.web.jersey.providers.jsonld.ObjectMapperProvider; import org.eclipse.edc.web.spi.WebServer; +import org.eclipse.edc.web.spi.WebService; import org.eclipse.edc.web.spi.configuration.WebServiceConfiguration; import org.eclipse.edc.web.spi.configuration.WebServiceConfigurer; import org.eclipse.edc.web.spi.configuration.WebServiceSettings; @@ -31,6 +36,7 @@ import java.net.URI; import static java.lang.String.format; +import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; /** * Tells all the Control API controllers under which context alias they need to register their resources: either @@ -56,14 +62,25 @@ public class ControlApiConfigurationExtension implements ServiceExtension { .useDefaultContext(true) .name(WEB_SERVICE_NAME) .build(); + private static final String CONTROL_SCOPE = "CONTROL_API"; + @Inject private WebServer webServer; @Inject private WebServiceConfigurer configurator; + @Inject + private WebService webService; + @Inject private Hostname hostname; + @Inject + private JsonLd jsonLd; + + @Inject + private TypeManager typeManager; + @Override public String name() { return NAME; @@ -73,9 +90,12 @@ public String name() { public void initialize(ServiceExtensionContext context) { var config = configurator.configure(context, webServer, SETTINGS); var callbackAddress = controlApiUrl(context, config); - + var jsonLdMapper = typeManager.getMapper(JSON_LD); context.registerService(ControlApiConfiguration.class, new ControlApiConfiguration(config)); context.registerService(ControlApiUrl.class, callbackAddress); + + webService.registerResource(SETTINGS.getContextAlias(), new ObjectMapperProvider(jsonLdMapper)); + webService.registerResource(SETTINGS.getContextAlias(), new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, CONTROL_SCOPE)); } private ControlApiUrl controlApiUrl(ServiceExtensionContext context, WebServiceConfiguration config) { diff --git a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-api/build.gradle.kts b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-api/build.gradle.kts index 288f0670d16..d05b8bb6de6 100644 --- a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-api/build.gradle.kts +++ b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-api/build.gradle.kts @@ -15,7 +15,7 @@ plugins { `java-library` `maven-publish` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/control-plane-api-client/build.gradle.kts b/extensions/control-plane/api/control-plane-api-client/build.gradle.kts index 41e3f956be5..c2d9f7e504c 100644 --- a/extensions/control-plane/api/control-plane-api-client/build.gradle.kts +++ b/extensions/control-plane/api/control-plane-api-client/build.gradle.kts @@ -29,6 +29,7 @@ dependencies { testImplementation(project(":core:data-plane-selector:data-plane-selector-core")) testImplementation(project(":extensions:control-plane:api:control-plane-api")) testImplementation(project(":extensions:common:auth:auth-tokenbased")) + testImplementation(project(":extensions:common:json-ld")) testImplementation(libs.awaitility) testImplementation(testFixtures(project(":core:common:lib:http-lib"))) diff --git a/extensions/control-plane/api/control-plane-api/build.gradle.kts b/extensions/control-plane/api/control-plane-api/build.gradle.kts index 4420e9c2032..4acfe5947eb 100644 --- a/extensions/control-plane/api/control-plane-api/build.gradle.kts +++ b/extensions/control-plane/api/control-plane-api/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/asset-api/build.gradle.kts b/extensions/control-plane/api/management-api/asset-api/build.gradle.kts index 9d3c765f45f..2a8284604f2 100644 --- a/extensions/control-plane/api/management-api/asset-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/asset-api/build.gradle.kts @@ -15,7 +15,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/catalog-api/build.gradle.kts b/extensions/control-plane/api/management-api/catalog-api/build.gradle.kts index 34187ed3e2d..0d0de0ff790 100644 --- a/extensions/control-plane/api/management-api/catalog-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/catalog-api/build.gradle.kts @@ -14,7 +14,7 @@ */ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/contract-agreement-api/build.gradle.kts b/extensions/control-plane/api/management-api/contract-agreement-api/build.gradle.kts index 254e3123603..7a7bd226b8f 100644 --- a/extensions/control-plane/api/management-api/contract-agreement-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/contract-agreement-api/build.gradle.kts @@ -16,7 +16,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/contract-definition-api/build.gradle.kts b/extensions/control-plane/api/management-api/contract-definition-api/build.gradle.kts index 81b6df6e287..0f08baf6e92 100644 --- a/extensions/control-plane/api/management-api/contract-definition-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/contract-definition-api/build.gradle.kts @@ -14,7 +14,7 @@ */ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/contract-negotiation-api/build.gradle.kts b/extensions/control-plane/api/management-api/contract-negotiation-api/build.gradle.kts index d2285e5325a..1b201c94831 100644 --- a/extensions/control-plane/api/management-api/contract-negotiation-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/contract-negotiation-api/build.gradle.kts @@ -12,7 +12,7 @@ */ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/edr-cache-api/build.gradle.kts b/extensions/control-plane/api/management-api/edr-cache-api/build.gradle.kts index 32c58cc10ec..5059dd369ca 100644 --- a/extensions/control-plane/api/management-api/edr-cache-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/edr-cache-api/build.gradle.kts @@ -15,7 +15,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/policy-definition-api/build.gradle.kts b/extensions/control-plane/api/management-api/policy-definition-api/build.gradle.kts index 4987db2b58e..ef3bd131ab6 100644 --- a/extensions/control-plane/api/management-api/policy-definition-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/policy-definition-api/build.gradle.kts @@ -15,7 +15,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/api/management-api/transfer-process-api/build.gradle.kts b/extensions/control-plane/api/management-api/transfer-process-api/build.gradle.kts index 058dfa575d4..19e5fabd8f7 100644 --- a/extensions/control-plane/api/management-api/transfer-process-api/build.gradle.kts +++ b/extensions/control-plane/api/management-api/transfer-process-api/build.gradle.kts @@ -13,7 +13,7 @@ */ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/provision/provision-http/build.gradle.kts b/extensions/control-plane/provision/provision-http/build.gradle.kts index da32c9439d1..48902b1b6ae 100644 --- a/extensions/control-plane/provision/provision-http/build.gradle.kts +++ b/extensions/control-plane/provision/provision-http/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/transfer/transfer-data-plane/build.gradle.kts b/extensions/control-plane/transfer/transfer-data-plane/build.gradle.kts index 7eeb2a878c0..ba3d64bd4c8 100644 --- a/extensions/control-plane/transfer/transfer-data-plane/build.gradle.kts +++ b/extensions/control-plane/transfer/transfer-data-plane/build.gradle.kts @@ -14,7 +14,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/control-plane/transfer/transfer-data-plane/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/proxy/ConsumerPullDataPlaneProxyResolver.java b/extensions/control-plane/transfer/transfer-data-plane/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/proxy/ConsumerPullDataPlaneProxyResolver.java index 2af9c39aa3f..1468e290615 100644 --- a/extensions/control-plane/transfer/transfer-data-plane/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/proxy/ConsumerPullDataPlaneProxyResolver.java +++ b/extensions/control-plane/transfer/transfer-data-plane/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/proxy/ConsumerPullDataPlaneProxyResolver.java @@ -33,6 +33,7 @@ import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; +@Deprecated(since = "0.5.1") public class ConsumerPullDataPlaneProxyResolver { private static final String PUBLIC_API_URL_PROPERTY_DEPRECATED = "publicApiUrl"; diff --git a/extensions/data-plane-selector/data-plane-selector-api/build.gradle.kts b/extensions/data-plane-selector/data-plane-selector-api/build.gradle.kts index bc4b14201b0..fb28457c7d0 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/build.gradle.kts +++ b/extensions/data-plane-selector/data-plane-selector-api/build.gradle.kts @@ -14,18 +14,20 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { api(project(":spi:common:core-spi")) api(project(":spi:data-plane-selector:data-plane-selector-spi")) implementation(project(":spi:common:transaction-spi")) + implementation(project(":core:common:lib:transform-lib")) implementation(project(":core:common:lib:util-lib")) + implementation(project(":core:common:lib:validator-lib")) implementation(project(":extensions:common:json-ld")) implementation(project(":extensions:common:api:management-api-configuration")) implementation(project(":extensions:common:api:api-core")) //for the exception mapper - implementation(project(":core:common:lib:validator-lib")) + implementation(libs.jakarta.rsApi) testImplementation(project(":core:common:lib:json-ld-lib")) @@ -33,10 +35,6 @@ dependencies { testImplementation(project(":core:common:junit")) testImplementation(project(":core:data-plane-selector:data-plane-selector-core")) testImplementation(project(":extensions:common:http")) - // for the TypeTransformerRegistryImpl - testImplementation(project(":core:common:lib:transform-lib")) - // for the JsonObject-To-DataAddress transformer - testImplementation(project(":extensions:common:api:management-api-configuration")) testImplementation(libs.restAssured) } diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java index 5318a7996ca..7e36ee23d93 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java @@ -19,8 +19,6 @@ import org.eclipse.edc.connector.dataplane.selector.api.v2.validation.DataPlaneInstanceValidator; import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectFromDataPlaneInstanceTransformer; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToSelectionRequestTransformer; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; @@ -28,6 +26,8 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataPlaneInstanceTransformer; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.WebService; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApi.java b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApi.java index ff478a919c8..1d41f69938f 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApi.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApi.java @@ -50,14 +50,16 @@ public interface DataplaneSelectorApi { @Operation(method = "POST", operationId = "addDataPlaneInstance", - description = "Adds one dataplane instance to the internal database of the selector", + description = "Adds one dataplane instance to the internal database of the selector. DEPRECATED: dataplanes should register themselves through control-api", requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = DataPlaneInstanceSchema.class))), responses = { @ApiResponse(responseCode = "200", description = "Entry was added successfully to the database", content = @Content(schema = @Schema(implementation = ApiCoreSchema.IdResponseSchema.class))), @ApiResponse(responseCode = "400", description = "Request body was malformed", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) - } + }, + deprecated = true ) @POST + @Deprecated(since = "0.6.2") JsonObject addDataPlaneInstance(JsonObject instance); @Operation(method = "GET", diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApiController.java b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApiController.java index 393699f50c2..e64e1ac2881 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApiController.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataplaneSelectorApiController.java @@ -37,7 +37,6 @@ import java.util.function.Supplier; import static jakarta.json.stream.JsonCollectors.toJsonArray; -import static java.util.Optional.ofNullable; import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.DATAPLANE_INSTANCE_TYPE; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; @@ -67,9 +66,7 @@ public JsonObject selectDataPlaneInstance(JsonObject requestObject) { var request = transformerRegistry.transform(requestObject, SelectionRequest.class) .orElseThrow(InvalidRequestException::new); - var dpi = ofNullable(request.getStrategy()) - .map(strategy -> catchException(() -> selectionService.select(request.getSource(), request.getDestination(), strategy, request.getTransferType()))) - .orElseGet(() -> catchException(() -> selectionService.select(request.getSource(), request.getDestination()))); + var dpi = catchException(() -> selectionService.select(request.getSource(), request.getDestination(), request.getStrategy(), request.getTransferType())); if (dpi == null) { return null; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java index fa4dd9a01fc..5631f8a962d 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java @@ -22,8 +22,6 @@ import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; import org.eclipse.edc.connector.dataplane.selector.spi.strategy.SelectionStrategyRegistry; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectFromDataPlaneInstanceTransformer; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToSelectionRequestTransformer; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; @@ -34,6 +32,8 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transaction.spi.NoopTransactionContext; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataPlaneInstanceTransformer; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.web.spi.WebService; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/TestFunctions.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/TestFunctions.java index b8324bfd04f..36f5c73e711 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/TestFunctions.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/TestFunctions.java @@ -17,19 +17,14 @@ import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; -import org.eclipse.edc.connector.dataplane.selector.api.v2.model.SelectionRequest; import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; -import org.eclipse.edc.spi.types.domain.DataAddress; import java.util.Set; -import static jakarta.json.Json.createObjectBuilder; import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_DEST_TYPES; import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_SOURCE_TYPES; import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.URL; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class TestFunctions { @@ -53,30 +48,9 @@ public static JsonObjectBuilder createInstanceJsonBuilder(String id) { .add(ID, id); } - public static JsonObject createSelectionRequestJson(String srcType, String destType, String strategy) { - return Json.createObjectBuilder() - .add(SelectionRequest.SOURCE_ADDRESS, createDataAddress(srcType)) - .add(SelectionRequest.DEST_ADDRESS, createDataAddress(destType)) - .add(SelectionRequest.STRATEGY, strategy) - .build(); - } - - public static JsonObject createSelectionRequestJson(String srcType, String destType) { - return Json.createObjectBuilder() - .add(SelectionRequest.SOURCE_ADDRESS, createDataAddress(srcType)) - .add(SelectionRequest.DEST_ADDRESS, createDataAddress(destType)) - .build(); - } - public static DataPlaneInstance.Builder createInstanceBuilder(String id) { return DataPlaneInstance.Builder.newInstance() .id(id) .url("http://somewhere.com:1234/api/v1"); } - - private static JsonObjectBuilder createDataAddress(String type) { - return createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY, type); - } } diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneApiSelectorTest.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneApiSelectorTest.java index 5e36fb6c6d0..bd8279d6eb1 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneApiSelectorTest.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneApiSelectorTest.java @@ -19,7 +19,6 @@ import jakarta.json.JsonObject; import org.eclipse.edc.connector.dataplane.selector.api.v2.model.SelectionRequest; import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToSelectionRequestTransformer; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; @@ -28,6 +27,7 @@ import org.eclipse.edc.transform.TypeTransformerRegistryImpl; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataAddressTransformer; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneSelectorApiControllerTest.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneSelectorApiControllerTest.java index 73485df8478..b2ee37c1865 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneSelectorApiControllerTest.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/DataPlaneSelectorApiControllerTest.java @@ -18,27 +18,31 @@ import jakarta.json.Json; import jakarta.json.JsonArray; import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import org.eclipse.edc.connector.dataplane.selector.api.v2.model.SelectionRequest; import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; import org.eclipse.edc.connector.dataplane.selector.spi.strategy.SelectionStrategy; import org.eclipse.edc.connector.dataplane.selector.spi.strategy.SelectionStrategyRegistry; import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.edc.spi.types.domain.DataAddress; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import java.io.IOException; import java.util.List; import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.connector.dataplane.selector.TestFunctions.createInstance; import static org.eclipse.edc.connector.dataplane.selector.TestFunctions.createInstanceBuilder; import static org.eclipse.edc.connector.dataplane.selector.TestFunctions.createInstanceJson; import static org.eclipse.edc.connector.dataplane.selector.TestFunctions.createInstanceJsonBuilder; -import static org.eclipse.edc.connector.dataplane.selector.TestFunctions.createSelectionRequestJson; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.hamcrest.Matchers.equalTo; @ComponentTest @@ -92,7 +96,7 @@ void addEntry(DataPlaneInstanceStore store) { } @Test - void addEntry_fails_whenMissingUrl(DataPlaneInstanceStore store) { + void addEntry_fails_whenMissingUrl() { var dpi = createInstanceJsonBuilder("test-id").build(); baseRequest() @@ -101,7 +105,6 @@ void addEntry_fails_whenMissingUrl(DataPlaneInstanceStore store) { .post() .then() .statusCode(400); - } @Test @@ -134,14 +137,16 @@ void select(DataPlaneInstanceStore store) { var dpi = createInstanceBuilder("test-id") .allowedSourceType("test-src1") .allowedDestType("test-dst1") + .allowedTransferType("transfer-type-1") .build(); var dpi2 = createInstanceBuilder("test-id") .allowedSourceType("test-src2") .allowedDestType("test-dst2") + .allowedTransferType("transfer-type-2") .build(); saveInstances(List.of(dpi, dpi2), store); - var rq = createSelectionRequestJson("test-src1", "test-dst1"); + var rq = createSelectionRequestJson("test-src1", "test-dst1", null, "transfer-type-1"); var result = baseRequest() .body(rq) @@ -165,8 +170,7 @@ void select_noneCanHandle_shouldReturnEmpty(DataPlaneInstanceStore store) { .build(); saveInstances(List.of(dpi, dpi2), store); - var rq = createSelectionRequestJson("notexist-src", "test-dst2"); - + var rq = createSelectionRequestJson("notexist-src", "test-dst2", null, "transfer-type"); baseRequest() .body(rq) @@ -178,7 +182,7 @@ void select_noneCanHandle_shouldReturnEmpty(DataPlaneInstanceStore store) { } @Test - void select_selectionStrategyNotFound(DataPlaneInstanceStore store) throws IOException { + void select_selectionStrategyNotFound(DataPlaneInstanceStore store) { var dpi = createInstanceBuilder("test-id") .allowedSourceType("test-src1") .allowedDestType("test-dst1") @@ -189,7 +193,7 @@ void select_selectionStrategyNotFound(DataPlaneInstanceStore store) throws IOExc .build(); saveInstances(List.of(dpi, dpi2), store); - var rq = createSelectionRequestJson("test-src1", "test-dst2", "notexist"); + var rq = createSelectionRequestJson("test-src1", "test-dst2", "notexist", "transfer-type1"); baseRequest() @@ -201,14 +205,16 @@ void select_selectionStrategyNotFound(DataPlaneInstanceStore store) throws IOExc } @Test - void select_withCustomStrategy(DataPlaneInstanceStore store, SelectionStrategyRegistry selectionStrategyRegistry) throws IOException { + void select_withCustomStrategy(DataPlaneInstanceStore store, SelectionStrategyRegistry selectionStrategyRegistry) { var dpi = createInstanceBuilder("test-id1") .allowedSourceType("test-src1") .allowedDestType("test-dst1") + .allowedTransferType("transfer-type-1") .build(); var dpi2 = createInstanceBuilder("test-id2") .allowedSourceType("test-src1") .allowedDestType("test-dst1") + .allowedTransferType("transfer-type-2") .build(); saveInstances(List.of(dpi, dpi2), store); @@ -226,7 +232,7 @@ public String getName() { selectionStrategyRegistry.add(myCustomStrategy); - var rq = createSelectionRequestJson("test-src1", "test-dst1", "myCustomStrategy"); + var rq = createSelectionRequestJson("test-src1", "test-dst1", "myCustomStrategy", "transfer-type-1"); var result = baseRequest() .body(rq) @@ -247,6 +253,24 @@ protected RequestSpecification baseRequest() { .when(); } + public JsonObject createSelectionRequestJson(String srcType, String destType, String strategy, String transferType) { + var builder = createObjectBuilder() + .add(SelectionRequest.SOURCE_ADDRESS, createDataAddress(srcType)) + .add(SelectionRequest.DEST_ADDRESS, createDataAddress(destType)) + .add(SelectionRequest.TRANSFER_TYPE, transferType); + + if (strategy != null) { + builder.add(SelectionRequest.STRATEGY, strategy); + } + return builder.build(); + } + + private JsonObjectBuilder createDataAddress(String type) { + return createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "DataAddress") + .add(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY, type); + } + private void saveInstances(List instances, DataPlaneInstanceStore store) { for (var instance : instances) { store.create(instance); diff --git a/extensions/data-plane-selector/data-plane-selector-client/build.gradle.kts b/extensions/data-plane-selector/data-plane-selector-client/build.gradle.kts index f3534509cb2..8113d5d2702 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/build.gradle.kts +++ b/extensions/data-plane-selector/data-plane-selector-client/build.gradle.kts @@ -18,17 +18,17 @@ plugins { dependencies { api(project(":spi:data-plane-selector:data-plane-selector-spi")) api(project(":spi:common:http-spi")) + api(project(":spi:common:transform-spi")) + implementation(project(":core:common:lib:transform-lib")) implementation(project(":core:common:lib:util-lib")) - implementation(project(":spi:common:transform-spi")) implementation(project(":extensions:common:json-ld")) - testImplementation(project(":extensions:common:http")) - testImplementation(project(":extensions:data-plane-selector:data-plane-selector-api")) - testImplementation(project(":extensions:common:api:api-core")) - testImplementation(project(":core:common:junit")) - testImplementation(project(":core:common:lib:transform-lib")) + testImplementation(project(":extensions:common:api:api-core")) + testImplementation(project(":extensions:common:http")) testImplementation(project(":extensions:common:http:lib:jersey-providers-lib")) + testImplementation(project(":extensions:data-plane-selector:data-plane-selector-api")) + testImplementation(project(":extensions:data-plane-selector:data-plane-selector-control-api")) testImplementation(testFixtures(project(":core:common:lib:http-lib"))) testImplementation(testFixtures(project(":extensions:common:http:jersey-core"))) diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java index 6e2db4341bf..83661dc84d0 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java @@ -14,6 +14,7 @@ package org.eclipse.edc.connector.dataplane.selector; +import jakarta.json.Json; import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.runtime.metamodel.annotation.Extension; @@ -24,15 +25,20 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataPlaneInstanceTransformer; -@Extension(value = "DataPlane Selector client") +import static java.util.Collections.emptyMap; +import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; + +@Extension(DataPlaneSelectorClientExtension.NAME) public class DataPlaneSelectorClientExtension implements ServiceExtension { - @Setting(value = "The DataPlane selector api URL") + public static final String NAME = "DataPlane Selector client"; + + @Setting(value = "DataPlane selector api URL", required = true) static final String DPF_SELECTOR_URL_SETTING = "edc.dpf.selector.url"; - private static final String DEFAULT_DATAPLANE_SELECTOR_STRATEGY = "random"; - @Setting(value = "Defines strategy for Data Plane instance selection in case Data Plane is not embedded in current runtime", defaultValue = DEFAULT_DATAPLANE_SELECTOR_STRATEGY) + @Setting(value = "Defines strategy for Data Plane instance selection in case Data Plane is not embedded in current runtime", defaultValue = DataPlaneSelectorService.DEFAULT_STRATEGY) private static final String DPF_SELECTOR_STRATEGY = "edc.dataplane.client.selector.strategy"; @Inject(required = false) @@ -44,10 +50,23 @@ public class DataPlaneSelectorClientExtension implements ServiceExtension { @Inject private TypeTransformerRegistry typeTransformerRegistry; + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + var builderFactory = Json.createBuilderFactory(emptyMap()); + var objectMapper = typeManager.getMapper(JSON_LD); + typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(builderFactory, objectMapper)); + } + @Provider public DataPlaneSelectorService dataPlaneSelectorService(ServiceExtensionContext context) { - var url = context.getConfig().getString(DPF_SELECTOR_URL_SETTING); - var selectionStrategy = context.getSetting(DPF_SELECTOR_STRATEGY, DEFAULT_DATAPLANE_SELECTOR_STRATEGY); + var config = context.getConfig(); + var url = config.getString(DPF_SELECTOR_URL_SETTING); + var selectionStrategy = config.getString(DPF_SELECTOR_STRATEGY, DataPlaneSelectorService.DEFAULT_STRATEGY); return new RemoteDataPlaneSelectorService(httpClient, url, typeManager.getMapper(), typeTransformerRegistry, selectionStrategy); } } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java index fc8786eb0a8..7e1c6dcaaf8 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java @@ -40,6 +40,7 @@ import static java.lang.String.format; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; @@ -123,38 +124,55 @@ public DataPlaneInstance select(DataAddress source, DataAddress destination, Str @Override public ServiceResult addInstance(DataPlaneInstance instance) { - throw new UnsupportedOperationException("not implemented"); - } + var transform = typeTransformerRegistry.transform(instance, JsonObject.class); + if (transform.failed()) { + return ServiceResult.badRequest(transform.getFailureDetail()); + } + var requestBody = Json.createObjectBuilder(transform.getContent()) + .add(CONTEXT, createObjectBuilder().add(VOCAB, EDC_NAMESPACE)) + .build(); + var body = RequestBody.create(requestBody.toString(), TYPE_JSON); - private R handleResponse(Response response, TypeReference tr, R defaultValue) { - if (response.isSuccessful()) { - R r = handleSuccess(response, tr); - return r == null ? defaultValue : r; - } else { - return handleError(response); - } - } + var request = new Request.Builder().post(body).url(url).build(); - private R handleSuccess(Response response, TypeReference tr) { try { - var body = response.body().string(); - if (StringUtils.isNullOrEmpty(body)) { - return null; + try (var response = httpClient.execute(request)) { + + handleResponse(response, null, null); + return ServiceResult.success(); } + } catch (IOException e) { + return ServiceResult.badRequest(e.getMessage()); + } + } - return mapper.readValue(body, tr); + private R handleResponse(Response response, TypeReference tr, R defaultValue) { + try (var responseBody = response.body()) { + var bodyAsString = responseBody == null ? null : responseBody.string(); + if (response.isSuccessful()) { + if (StringUtils.isNullOrEmpty(bodyAsString)) { + return null; + } + + if (tr != null) { + var r = mapper.readValue(bodyAsString, tr); + return r == null ? defaultValue : r; + } else { + return null; + } + + } else { + return switch (response.code()) { + case 400 -> throw new IllegalArgumentException("Remote API returned HTTP 400. " + bodyAsString); + case 404 -> null; + default -> + throw new IllegalArgumentException(format("An unknown error happened, HTTP Status = %d", response.code())); + }; + } } catch (IOException e) { throw new EdcException(e); } } - private R handleError(Response response) { - return switch (response.code()) { - case 400 -> throw new IllegalArgumentException("Remote API returned HTTP 400"); - case 404 -> null; - default -> - throw new IllegalArgumentException(format("An unknown error happened, HTTP Status = %d", response.code())); - }; - } } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java index 58fb207a088..a9316bc1114 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java @@ -18,6 +18,9 @@ import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.configuration.ConfigFactory; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataPlaneInstanceTransformer; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,11 +30,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.eclipse.edc.connector.dataplane.selector.DataPlaneSelectorClientExtension.DPF_SELECTOR_URL_SETTING; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) class DataPlaneSelectorClientExtensionTest { + private final TypeTransformerRegistry typeTransformerRegistry = mock(); + + @BeforeEach + void setUp(ServiceExtensionContext context) { + context.registerService(TypeTransformerRegistry.class, typeTransformerRegistry); + } + @Test void dataPlaneSelectorService_shouldReturnRemoteService(DataPlaneSelectorClientExtension extension, ServiceExtensionContext context) { when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of(DPF_SELECTOR_URL_SETTING, "http://any"))); @@ -49,4 +62,10 @@ void dataPlaneSelectorService_shouldThrowException_whenUrlNotConfigured(DataPlan .hasMessageContaining("No setting found"); } + @Test + void initialize_shouldRegisterTransformer(DataPlaneSelectorClientExtension extension, ServiceExtensionContext context) { + extension.initialize(context); + + verify(typeTransformerRegistry).register(isA(JsonObjectFromDataPlaneInstanceTransformer.class)); + } } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorServiceTest.java b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorServiceTest.java index f3ffaf3bdac..8753a274900 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorServiceTest.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorServiceTest.java @@ -15,28 +15,33 @@ package org.eclipse.edc.connector.dataplane.selector; import jakarta.json.Json; +import org.eclipse.edc.api.transformer.JsonObjectFromIdResponseTransformer; import org.eclipse.edc.connector.dataplane.selector.api.v2.DataplaneSelectorApiController; +import org.eclipse.edc.connector.dataplane.selector.control.api.DataplaneSelectorControlApiController; import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectFromDataPlaneInstanceTransformer; -import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.connector.dataplane.selector.transformer.JsonObjectToSelectionRequestTransformer; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.util.JacksonJsonLd; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.transform.TypeTransformerRegistryImpl; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataAddressTransformer; +import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataPlaneInstanceTransformer; import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataAddressTransformer; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.validator.spi.ValidationResult; import org.eclipse.edc.web.jersey.providers.jsonld.JerseyJsonLdInterceptor; import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.time.Clock; @@ -46,16 +51,17 @@ import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.http.client.testfixtures.HttpTestUtils.testHttpClient; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ComponentTest -class RemoteDataPlaneSelectorServiceTest extends RestControllerTestBase { +class RemoteDataPlaneSelectorServiceTest { - private static final String BASE_URL = "http://localhost:%d/v2/dataplanes"; private static final DataPlaneSelectorService SELECTOR_SERVICE_MOCK = mock(); private static final TypeManager TYPE_MANAGER = new JacksonTypeManager(); private final TypeTransformerRegistry typeTransformerRegistry = new TypeTransformerRegistryImpl(); @@ -68,58 +74,107 @@ public static void prepare() { TYPE_MANAGER.registerContext(JSON_LD, JacksonJsonLd.createObjectMapper()); } - @BeforeEach - void setUp() { - var factory = Json.createBuilderFactory(Map.of()); - typeTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(factory)); - typeTransformerRegistry.register(new JsonObjectToDataAddressTransformer()); - typeTransformerRegistry.register(new JsonObjectToSelectionRequestTransformer()); - typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(factory, JacksonJsonLd.createObjectMapper())); - typeTransformerRegistry.register(new JsonObjectToDataPlaneInstanceTransformer()); - typeTransformerRegistry.register(new JsonValueToGenericTypeTransformer(objectMapper)); - var url = format(BASE_URL, port); - service = new RemoteDataPlaneSelectorService(testHttpClient(), url, JacksonJsonLd.createObjectMapper(), typeTransformerRegistry, "selectionStrategy"); - } + @Nested + class Select extends RestControllerTestBase { - @Test - void getAll() { - when(SELECTOR_SERVICE_MOCK.getAll()).thenReturn(List.of(createInstance("test-inst1"), createInstance("test-inst2"))); + private static final String BASE_URL = "http://localhost:%d/v2/dataplanes"; - var result = service.getAll(); + @BeforeEach + void setUp() { + var factory = Json.createBuilderFactory(Map.of()); + typeTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(factory)); + typeTransformerRegistry.register(new JsonObjectToDataAddressTransformer()); + typeTransformerRegistry.register(new JsonObjectToSelectionRequestTransformer()); + typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(factory, JacksonJsonLd.createObjectMapper())); + typeTransformerRegistry.register(new JsonObjectToDataPlaneInstanceTransformer()); + typeTransformerRegistry.register(new JsonObjectFromIdResponseTransformer(factory)); + typeTransformerRegistry.register(new JsonValueToGenericTypeTransformer(objectMapper)); + var url = format(BASE_URL, port); + service = new RemoteDataPlaneSelectorService(testHttpClient(), url, JacksonJsonLd.createObjectMapper(), typeTransformerRegistry, "selectionStrategy"); + } - assertThat(result).hasSize(2).extracting(DataPlaneInstance::getId).containsExactlyInAnyOrder("test-inst1", "test-inst2"); - } + @Test + void getAll() { + when(SELECTOR_SERVICE_MOCK.getAll()).thenReturn(List.of(createInstance("test-inst1"), createInstance("test-inst2"))); - @Test - void find() { - var expected = createInstance("some-instance"); - when(SELECTOR_SERVICE_MOCK.select(any(), any())).thenReturn(expected); + var result = service.getAll(); - var result = service.select(DataAddress.Builder.newInstance().type("test1").build(), DataAddress.Builder.newInstance().type("test2").build()); + assertThat(result).hasSize(2).extracting(DataPlaneInstance::getId).containsExactlyInAnyOrder("test-inst1", "test-inst2"); + } - assertThat(result).usingRecursiveComparison().isEqualTo(expected); + @Test + void find() { + var expected = createInstance("some-instance"); + when(SELECTOR_SERVICE_MOCK.select(any(), any(), any(), any())).thenReturn(expected); - } + var result = service.select(DataAddress.Builder.newInstance().type("test1").build(), DataAddress.Builder.newInstance().type("test2").build()); - @Test - void find_withTransferType() { - var expected = createInstance("some-instance"); - when(SELECTOR_SERVICE_MOCK.select(any(), any(), eq("random"), eq("transferType"))).thenReturn(expected); + assertThat(result).usingRecursiveComparison().isEqualTo(expected); + } - var result = service.select(DataAddress.Builder.newInstance().type("test1").build(), DataAddress.Builder.newInstance().type("test2").build(), "random", "transferType"); + @Test + void find_withTransferType() { + var expected = createInstance("some-instance"); + when(SELECTOR_SERVICE_MOCK.select(any(), any(), eq("random"), eq("transferType"))).thenReturn(expected); - assertThat(result).usingRecursiveComparison().isEqualTo(expected); + var result = service.select(DataAddress.Builder.newInstance().type("test1").build(), DataAddress.Builder.newInstance().type("test2").build(), "random", "transferType"); + + assertThat(result).usingRecursiveComparison().isEqualTo(expected); + } + + @Override + protected Object controller() { + return new DataplaneSelectorApiController(SELECTOR_SERVICE_MOCK, typeTransformerRegistry, validator, Clock.systemUTC()); + } + + @Override + protected Object additionalResource() { + return new JerseyJsonLdInterceptor(new TitaniumJsonLd(mock()), JacksonJsonLd.createObjectMapper(), "scope"); + } - } - @Override - protected Object controller() { - return new DataplaneSelectorApiController(SELECTOR_SERVICE_MOCK, typeTransformerRegistry, validator, Clock.systemUTC()); } - @Override - protected Object additionalResource() { - return new JerseyJsonLdInterceptor(new TitaniumJsonLd(mock()), JacksonJsonLd.createObjectMapper(), "scope"); + @Nested + class AddInstance extends RestControllerTestBase { + + private static final String BASE_URL = "http://localhost:%d/v1/dataplanes"; + + @BeforeEach + void setUp() { + var factory = Json.createBuilderFactory(Map.of()); + typeTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(factory)); + typeTransformerRegistry.register(new JsonObjectToDataAddressTransformer()); + typeTransformerRegistry.register(new JsonObjectToSelectionRequestTransformer()); + typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(factory, JacksonJsonLd.createObjectMapper())); + typeTransformerRegistry.register(new JsonObjectToDataPlaneInstanceTransformer()); + typeTransformerRegistry.register(new JsonObjectFromIdResponseTransformer(factory)); + typeTransformerRegistry.register(new JsonValueToGenericTypeTransformer(objectMapper)); + var url = format(BASE_URL, port); + service = new RemoteDataPlaneSelectorService(testHttpClient(), url, JacksonJsonLd.createObjectMapper(), typeTransformerRegistry, "selectionStrategy"); + } + + @Test + void addInstance() { + when(validator.validate(any(), any())).thenReturn(ValidationResult.success()); + when(SELECTOR_SERVICE_MOCK.addInstance(any())).thenReturn(ServiceResult.success()); + var instance = createInstance("dataPlaneId"); + + var result = service.addInstance(instance); + + assertThat(result).isSucceeded(); + verify(SELECTOR_SERVICE_MOCK).addInstance(any()); + } + + @Override + protected Object controller() { + return new DataplaneSelectorControlApiController(validator, typeTransformerRegistry, SELECTOR_SERVICE_MOCK, Clock.systemUTC()); + } + + @Override + protected Object additionalResource() { + return new JerseyJsonLdInterceptor(new TitaniumJsonLd(mock()), JacksonJsonLd.createObjectMapper(), "scope"); + } } private DataPlaneInstance createInstance(String id) { @@ -128,4 +183,5 @@ private DataPlaneInstance createInstance(String id) { .url("http://somewhere.com:1234/api/v1") .build(); } + } diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/build.gradle.kts b/extensions/data-plane-selector/data-plane-selector-control-api/build.gradle.kts new file mode 100644 index 00000000000..1233a4c1aa1 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/build.gradle.kts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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 + * + */ + + +plugins { + `java-library` + id(libs.plugins.swagger.get().pluginId) +} + +dependencies { + api(project(":spi:common:web-spi")) + api(project(":spi:data-plane-selector:data-plane-selector-spi")) + + implementation(project(":core:common:lib:transform-lib")) + implementation(project(":core:common:lib:validator-lib")) + implementation(project(":extensions:common:api:api-core")) + implementation(project(":extensions:common:api:control-api-configuration")) + implementation(libs.jakarta.rsApi) + + testImplementation(project(":core:common:junit")) + + testImplementation(testFixtures(project(":extensions:common:http:jersey-core"))) + testImplementation(libs.restAssured) + +} + +edcBuild { + swagger { + apiGroup.set("control-api") + } +} + + + diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataPlaneInstanceValidator.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataPlaneInstanceValidator.java new file mode 100644 index 00000000000..70f21c4b129 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataPlaneInstanceValidator.java @@ -0,0 +1,44 @@ +/* + * 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.edc.connector.dataplane.selector.control.api; + +import jakarta.json.JsonObject; +import org.eclipse.edc.validator.jsonobject.JsonObjectValidator; +import org.eclipse.edc.validator.jsonobject.validators.MandatoryArray; +import org.eclipse.edc.validator.jsonobject.validators.MandatoryIdNotBlank; +import org.eclipse.edc.validator.jsonobject.validators.MandatoryValue; +import org.eclipse.edc.validator.spi.Validator; + +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_DEST_TYPES; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_SOURCE_TYPES; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_TRANSFER_TYPES; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.URL; + +/** + * Contains the DataPlaneInstance validator definition + */ +public class DataPlaneInstanceValidator { + + public static Validator instance() { + return JsonObjectValidator.newValidator() + .verifyId(MandatoryIdNotBlank::new) + .verify(URL, MandatoryValue::new) + .verify(ALLOWED_SOURCE_TYPES, MandatoryArray.min(1)) + .verify(ALLOWED_DEST_TYPES, MandatoryArray.min(1)) + .verify(ALLOWED_TRANSFER_TYPES, MandatoryArray.min(1)) + .build(); + } + +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApi.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApi.java new file mode 100644 index 00000000000..0c61297e2e7 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApi.java @@ -0,0 +1,102 @@ +/* + * 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.edc.connector.dataplane.selector.control.api; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.json.JsonObject; +import jakarta.ws.rs.HttpMethod; +import jakarta.ws.rs.POST; +import org.eclipse.edc.api.model.ApiCoreSchema; + +import java.net.URL; +import java.util.Set; + +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.DATAPLANE_INSTANCE_TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; + +@OpenAPIDefinition +@Tag(name = "Dataplane Selector") +public interface DataplaneSelectorControlApi { + + @Operation(method = HttpMethod.POST, + operationId = "registerDataplane", + description = "Register new Dataplane", + requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = DataPlaneInstanceSchema.class))), + responses = { + @ApiResponse(responseCode = "200", description = "Dataplane successfully registered", + content = @Content(schema = @Schema(implementation = ApiCoreSchema.IdResponseSchema.class))), + @ApiResponse(responseCode = "400", description = "Request body was malformed", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))), + @ApiResponse(responseCode = "409", description = "Resource already exists", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) + }) + @POST + JsonObject registerDataplane(JsonObject request); + + @Operation(method = HttpMethod.DELETE, + operationId = "unregisterDataplane", + description = "Unregister existing Dataplane", + responses = { + @ApiResponse(responseCode = "204", description = "Dataplane successfully unregistered"), + @ApiResponse(responseCode = "400", description = "Request body was malformed", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))), + @ApiResponse(responseCode = "404", description = "Resource not found", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) + } + ) + @POST + void unregisterDataplane(String id); + + @Schema(example = DataPlaneInstanceSchema.DATAPLANE_INSTANCE_EXAMPLE) + record DataPlaneInstanceSchema( + @Schema(name = CONTEXT, requiredMode = REQUIRED) + Object context, + @Schema(name = TYPE, example = DATAPLANE_INSTANCE_TYPE) + String type, + @Schema(name = ID, requiredMode = REQUIRED) + String id, + @Schema(requiredMode = REQUIRED) + URL url, + @Schema(requiredMode = REQUIRED) + Set allowedSourceTypes, + @Schema(requiredMode = REQUIRED) + Set allowedDestTypes) { + public static final String DATAPLANE_INSTANCE_EXAMPLE = """ + { + "@context": { + "@vocab": "https://w3id.org/edc/v0.0.1/ns/" + }, + "@id": "your-dataplane-id", + "url": "http://somewhere.com:1234/api/v1", + "allowedSourceTypes": [ + "source-type1", + "source-type2" + ], + "allowedDestTypes": ["your-dest-type"], + "allowedTransferTypes": ["transfer-type"] + } + """; + } +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiController.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiController.java new file mode 100644 index 00000000000..b171fe97eda --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiController.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api; + +import jakarta.json.JsonObject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import org.eclipse.edc.api.model.IdResponse; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.web.spi.exception.InvalidRequestException; +import org.eclipse.edc.web.spi.exception.ValidationFailureException; + +import java.time.Clock; + +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; + +@Consumes(APPLICATION_JSON) +@Produces(APPLICATION_JSON) +@Path("/v1/dataplanes") +public class DataplaneSelectorControlApiController implements DataplaneSelectorControlApi { + + private final JsonObjectValidatorRegistry validatorRegistry; + private final TypeTransformerRegistry transformerRegistry; + private final DataPlaneSelectorService service; + private final Clock clock; + + public DataplaneSelectorControlApiController(JsonObjectValidatorRegistry validatorRegistry, + TypeTransformerRegistry transformerRegistry, + DataPlaneSelectorService service, Clock clock) { + + this.validatorRegistry = validatorRegistry; + this.transformerRegistry = transformerRegistry; + this.service = service; + this.clock = clock; + } + + @Override + @POST + public JsonObject registerDataplane(JsonObject request) { + validatorRegistry.validate(DataPlaneInstance.DATAPLANE_INSTANCE_TYPE, request).orElseThrow(ValidationFailureException::new); + + var dataplane = transformerRegistry.transform(request, DataPlaneInstance.class).orElseThrow(InvalidRequestException::new); + + service.addInstance(dataplane) + .orElseThrow(exceptionMapper(DataPlaneInstance.class, dataplane.getId())); + + var idResponse = IdResponse.Builder.newInstance() + .id(dataplane.getId()) + .createdAt(clock.millis()) + .build(); + + return transformerRegistry.transform(idResponse, JsonObject.class) + .orElseThrow(f -> new EdcException(f.getFailureDetail())); + } + + @Override + @DELETE + @Path("/{id}") + public void unregisterDataplane(@PathParam("id") String id) { + throw new UnsupportedOperationException("not yet implemented"); + } +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java new file mode 100644 index 00000000000..af2d92b2414 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api; + +import org.eclipse.edc.connector.api.control.configuration.ControlApiConfiguration; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +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.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.web.spi.WebService; + +import java.time.Clock; + +import static org.eclipse.edc.connector.dataplane.selector.control.api.DataplaneSelectorControlApiExtension.NAME; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.DATAPLANE_INSTANCE_TYPE; + +@Extension(NAME) +public class DataplaneSelectorControlApiExtension implements ServiceExtension { + + public static final String NAME = "Dataplane Selector Control API"; + + @Inject + private WebService webService; + + @Inject + private ControlApiConfiguration controlApiConfiguration; + + @Inject + private JsonObjectValidatorRegistry validatorRegistry; + + @Inject + private TypeTransformerRegistry typeTransformerRegistry; + + @Inject + private DataPlaneSelectorService dataPlaneSelectorService; + + @Inject + private Clock clock; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + validatorRegistry.register(DATAPLANE_INSTANCE_TYPE, DataPlaneInstanceValidator.instance()); + + typeTransformerRegistry.register(new JsonObjectToDataPlaneInstanceTransformer()); + + var controller = new DataplaneSelectorControlApiController(validatorRegistry, typeTransformerRegistry, dataPlaneSelectorService, clock); + webService.registerResource(controlApiConfiguration.getContextAlias(), controller); + } +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 00000000000..3cc857ab6ed --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,16 @@ +# +# Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api.DataplaneSelectorControlApiExtension + diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataPlaneInstanceValidatorTest.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataPlaneInstanceValidatorTest.java new file mode 100644 index 00000000000..43175a499fd --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataPlaneInstanceValidatorTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api; + +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.eclipse.edc.validator.spi.ValidationFailure; +import org.eclipse.edc.validator.spi.Validator; +import org.eclipse.edc.validator.spi.Violation; +import org.junit.jupiter.api.Test; + +import static jakarta.json.Json.createArrayBuilder; +import static jakarta.json.Json.createObjectBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_DEST_TYPES; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_SOURCE_TYPES; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.ALLOWED_TRANSFER_TYPES; +import static org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance.URL; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; + +class DataPlaneInstanceValidatorTest { + + private final Validator validator = DataPlaneInstanceValidator.instance(); + + @Test + void shouldPass_whenJsonIsValid() { + var json = createObjectBuilder() + .add(ID, "id") + .add(URL, value("url")) + .add(ALLOWED_SOURCE_TYPES, createArrayBuilder().add(value("src"))) + .add(ALLOWED_DEST_TYPES, createArrayBuilder().add(value("dest"))) + .add(ALLOWED_TRANSFER_TYPES, createArrayBuilder().add(value("transfer"))) + .build(); + + var result = validator.validate(json); + + assertThat(result).isSucceeded(); + } + + @Test + void shouldFail_whenMandatoryFieldsAreNotSet() { + var json = createObjectBuilder().build(); + + var result = validator.validate(json); + + assertThat(result).isFailed().extracting(ValidationFailure::getViolations, InstanceOfAssertFactories.list(Violation.class)) + .isNotEmpty() + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ID)) + .anySatisfy(v -> assertThat(v.path()).isEqualTo(URL)) + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ALLOWED_SOURCE_TYPES)) + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ALLOWED_DEST_TYPES)) + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ALLOWED_TRANSFER_TYPES)); + } + + @Test + void shouldFail_whenAllowedTypesAreEmpty() { + var json = createObjectBuilder() + .add(ALLOWED_SOURCE_TYPES, createArrayBuilder()) + .add(ALLOWED_DEST_TYPES, createArrayBuilder()) + .add(ALLOWED_TRANSFER_TYPES, createArrayBuilder()) + .build(); + + var result = validator.validate(json); + + assertThat(result).isFailed().extracting(ValidationFailure::getViolations, InstanceOfAssertFactories.list(Violation.class)) + .isNotEmpty() + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ALLOWED_SOURCE_TYPES)) + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ALLOWED_DEST_TYPES)) + .anySatisfy(v -> assertThat(v.path()).isEqualTo(ALLOWED_TRANSFER_TYPES)); + } + + private JsonArrayBuilder value(String value) { + return createArrayBuilder().add(createObjectBuilder().add(VALUE, value)); + } +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiControllerTest.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiControllerTest.java new file mode 100644 index 00000000000..41c20ac0528 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiControllerTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; +import org.eclipse.edc.junit.annotations.ApiTest; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.ServiceResult; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.validator.spi.ValidationResult; +import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.Clock; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.validator.spi.Violation.violation; +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ApiTest +class DataplaneSelectorControlApiControllerTest extends RestControllerTestBase { + + private final JsonObjectValidatorRegistry validatorRegistry = mock(); + private final TypeTransformerRegistry typeTransformerRegistry = mock(); + private final DataPlaneSelectorService service = mock(); + private final Clock clock = mock(); + + @Nested + class Register { + + @Test + void shouldRegisterDataplane() { + var dataplaneInstance = DataPlaneInstance.Builder.newInstance().url("http://url").build(); + var response = Json.createObjectBuilder().add(ID, "id").build(); + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); + when(typeTransformerRegistry.transform(any(), eq(DataPlaneInstance.class))).thenReturn(Result.success(dataplaneInstance)); + when(service.addInstance(any())).thenReturn(ServiceResult.success()); + when(typeTransformerRegistry.transform(any(), eq(JsonObject.class))).thenReturn(Result.success(response)); + + given() + .port(port) + .contentType(JSON) + .body(Json.createObjectBuilder().build()) + .post("/v1/dataplanes") + .then() + .statusCode(200) + .body(ID, is("id")); + + verify(service).addInstance(dataplaneInstance); + } + + @Test + void shouldReturnBadRequest_whenValidationFails() { + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.failure(violation("error", "/path"))); + + given() + .port(port) + .contentType(JSON) + .body(Json.createObjectBuilder().build()) + .post("/v1/dataplanes") + .then() + .statusCode(400); + + verifyNoInteractions(service, typeTransformerRegistry); + } + + @Test + void shouldReturnBadRequest_whenIngressTransformationFails() { + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); + when(typeTransformerRegistry.transform(any(), eq(DataPlaneInstance.class))).thenReturn(Result.failure("error")); + + given() + .port(port) + .contentType(JSON) + .body(Json.createObjectBuilder().build()) + .post("/v1/dataplanes") + .then() + .statusCode(400); + + verifyNoInteractions(service); + } + + @Test + void shouldFail_whenServiceFails() { + var dataplaneInstance = DataPlaneInstance.Builder.newInstance().url("http://url").build(); + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); + when(typeTransformerRegistry.transform(any(), eq(DataPlaneInstance.class))).thenReturn(Result.success(dataplaneInstance)); + when(service.addInstance(any())).thenReturn(ServiceResult.conflict("conflict")); + + given() + .port(port) + .contentType(JSON) + .body(Json.createObjectBuilder().build()) + .post("/v1/dataplanes") + .then() + .statusCode(409); + } + + @Test + void shouldFail_whenEgressTransformationFails() { + var dataplaneInstance = DataPlaneInstance.Builder.newInstance().url("http://url").build(); + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); + when(typeTransformerRegistry.transform(any(), eq(DataPlaneInstance.class))).thenReturn(Result.success(dataplaneInstance)); + when(service.addInstance(any())).thenReturn(ServiceResult.success()); + when(typeTransformerRegistry.transform(any(), eq(JsonObject.class))).thenReturn(Result.failure("error")); + + given() + .port(port) + .contentType(JSON) + .body(Json.createObjectBuilder().build()) + .post("/v1/dataplanes") + .then() + .statusCode(500); + } + } + + @Override + protected Object controller() { + return new DataplaneSelectorControlApiController(validatorRegistry, typeTransformerRegistry, service, clock); + } + +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java new file mode 100644 index 00000000000..e6fdd7b63b2 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api; + +import org.eclipse.edc.connector.api.control.configuration.ControlApiConfiguration; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; +import org.eclipse.edc.validator.jsonobject.JsonObjectValidator; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.web.spi.WebService; +import org.eclipse.edc.web.spi.configuration.WebServiceConfiguration; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@ExtendWith(DependencyInjectionExtension.class) +class DataplaneSelectorControlApiExtensionTest { + + private final WebService webService = mock(); + private final JsonObjectValidatorRegistry validatorRegistry = mock(); + private final TypeTransformerRegistry typeTransformerRegistry = mock(); + private final WebServiceConfiguration controlApiConfiguration = WebServiceConfiguration.Builder.newInstance() + .contextAlias("control-alias") + .path("/path") + .port(42) + .build(); + + @BeforeEach + void setUp(ServiceExtensionContext context) { + context.registerService(WebService.class, webService); + context.registerService(JsonObjectValidatorRegistry.class, validatorRegistry); + context.registerService(TypeTransformerRegistry.class, typeTransformerRegistry); + context.registerService(ControlApiConfiguration.class, new ControlApiConfiguration(controlApiConfiguration)); + } + + @Test + void shouldRegisterController(DataplaneSelectorControlApiExtension extension, ServiceExtensionContext context) { + extension.initialize(context); + + verify(webService).registerResource(eq("control-alias"), isA(DataplaneSelectorControlApiController.class)); + } + + @Test + void shouldRegisterValidator(DataplaneSelectorControlApiExtension extension, ServiceExtensionContext context) { + extension.initialize(context); + + verify(validatorRegistry).register(eq(DataPlaneInstance.DATAPLANE_INSTANCE_TYPE), isA(JsonObjectValidator.class)); + } + + @Test + void shouldRegisterTransformers(DataplaneSelectorControlApiExtension extension, ServiceExtensionContext context) { + extension.initialize(context); + + verify(typeTransformerRegistry).register(isA(JsonObjectToDataPlaneInstanceTransformer.class)); + } +} diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiTest.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiTest.java new file mode 100644 index 00000000000..eadc1a7eae1 --- /dev/null +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.selector.control.api; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.JsonObject; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; +import org.eclipse.edc.jsonld.JsonLdExtension; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.eclipse.edc.transform.TypeTransformerRegistryImpl; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToDataPlaneInstanceTransformer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.connector.dataplane.selector.control.api.DataplaneSelectorControlApi.DataPlaneInstanceSchema.DATAPLANE_INSTANCE_EXAMPLE; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.edc.junit.extensions.TestServiceExtensionContext.testServiceExtensionContext; + +class DataplaneSelectorControlApiTest { + + private final ObjectMapper objectMapper = JacksonJsonLd.createObjectMapper(); + private final JsonLd jsonLd = new JsonLdExtension().createJsonLdService(testServiceExtensionContext()); + private final TypeTransformerRegistry transformer = new TypeTransformerRegistryImpl(); + + @BeforeEach + void setUp() { + transformer.register(new JsonObjectToDataPlaneInstanceTransformer()); + } + + @Test + void dataplaneInstanceExample() throws JsonProcessingException { + var validator = DataPlaneInstanceValidator.instance(); + + var jsonObject = objectMapper.readValue(DATAPLANE_INSTANCE_EXAMPLE, JsonObject.class); + assertThat(jsonObject).isNotNull(); + + var expanded = jsonLd.expand(jsonObject); + assertThat(expanded).isSucceeded() + .satisfies(exp -> assertThat(validator.validate(exp)).isSucceeded()) + .extracting(e -> transformer.transform(e, DataPlaneInstance.class)) + .satisfies(transformResult -> assertThat(transformResult).isSucceeded() + .satisfies(transformed -> { + assertThat(transformed.getId()).isNotBlank(); + assertThat(transformed.getUrl()).isNotNull(); + assertThat(transformed.getAllowedDestTypes()).isNotEmpty(); + assertThat(transformed.getAllowedDestTypes()).isNotEmpty(); + assertThat(transformed.getAllowedTransferTypes()).isNotEmpty(); + })); + } +} diff --git a/extensions/data-plane/data-plane-control-api/build.gradle.kts b/extensions/data-plane/data-plane-control-api/build.gradle.kts index 3152c2710b9..7bdaa784727 100644 --- a/extensions/data-plane/data-plane-control-api/build.gradle.kts +++ b/extensions/data-plane/data-plane-control-api/build.gradle.kts @@ -17,7 +17,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java b/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java index 763d3ef058c..1ec2cb1165b 100644 --- a/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java +++ b/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java @@ -110,7 +110,6 @@ public class DataPlaneHttpIntegrationTests { @RegisterExtension static EdcRuntimeExtension dataPlane = new EdcRuntimeExtension( - ":launchers:data-plane-server", "data-plane-server", Map.of( "web.http.public.port", valueOf(PUBLIC_API_PORT), @@ -118,7 +117,16 @@ public class DataPlaneHttpIntegrationTests { "web.http.control.port", valueOf(CONTROL_API_PORT), "web.http.control.path", CONTROL_PATH, "edc.dataplane.token.validation.endpoint", VALIDATION_API_HOST - )); + ), + ":extensions:common:metrics:micrometer-core", + ":core:data-plane:data-plane-core", + ":extensions:common:http", + ":extensions:common:json-ld", + ":extensions:common:configuration:configuration-filesystem", + ":extensions:data-plane:data-plane-http", + ":extensions:data-plane:data-plane-control-api", + ":extensions:data-plane:data-plane-public-api" + ); @BeforeAll public static void setUp() { diff --git a/extensions/data-plane/data-plane-public-api-v2/build.gradle.kts b/extensions/data-plane/data-plane-public-api-v2/build.gradle.kts index f2f3bd2358a..14a509ba43e 100644 --- a/extensions/data-plane/data-plane-public-api-v2/build.gradle.kts +++ b/extensions/data-plane/data-plane-public-api-v2/build.gradle.kts @@ -17,7 +17,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/data-plane/data-plane-public-api/build.gradle.kts b/extensions/data-plane/data-plane-public-api/build.gradle.kts index 5d03a97dcf5..1516ceb8107 100644 --- a/extensions/data-plane/data-plane-public-api/build.gradle.kts +++ b/extensions/data-plane/data-plane-public-api/build.gradle.kts @@ -17,7 +17,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/data-plane/data-plane-self-registration/build.gradle.kts b/extensions/data-plane/data-plane-self-registration/build.gradle.kts new file mode 100644 index 00000000000..537d2b18627 --- /dev/null +++ b/extensions/data-plane/data-plane-self-registration/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 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 + * + */ + + +plugins { + `java-library` +} + +dependencies { + api(project(":extensions:data-plane-selector:data-plane-selector-api")) + + implementation(project(":extensions:common:api:control-api-configuration")) + + testImplementation(project(":core:common:junit")) +} + + diff --git a/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java b/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java new file mode 100644 index 00000000000..ac9bc022449 --- /dev/null +++ b/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.registration; + +import org.eclipse.edc.connector.controlplane.transfer.spi.callback.ControlApiUrl; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; +import org.eclipse.edc.connector.dataplane.spi.iam.PublicEndpointGeneratorService; +import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.domain.transfer.FlowType; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toSet; +import static org.eclipse.edc.connector.dataplane.registration.DataplaneSelfRegistrationExtension.NAME; +import static org.eclipse.edc.spi.types.domain.transfer.FlowType.PULL; +import static org.eclipse.edc.spi.types.domain.transfer.FlowType.PUSH; + +@Extension(NAME) +public class DataplaneSelfRegistrationExtension implements ServiceExtension { + + public static final String NAME = "Dataplane Self Registration"; + + @Inject + private DataPlaneSelectorService dataPlaneSelectorService; + + @Inject + private ControlApiUrl controlApiUrl; + + @Inject + private PipelineService pipelineService; + + @Inject + private PublicEndpointGeneratorService publicEndpointGeneratorService; + private ServiceExtensionContext context; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + this.context = context; + } + + @Override + public void start() { + var transferTypes = Stream.concat( + toTransferTypes(PULL, publicEndpointGeneratorService.supportedDestinationTypes()), + toTransferTypes(PUSH, pipelineService.supportedSinkTypes()) + ); + + var instance = DataPlaneInstance.Builder.newInstance() + .id(context.getRuntimeId()) + .url(controlApiUrl.get().toString() + "/v1/dataflows") + .allowedSourceTypes(pipelineService.supportedSourceTypes()) + .allowedDestTypes(pipelineService.supportedSinkTypes()) + .allowedTransferType(transferTypes.collect(toSet())) + .build(); + + dataPlaneSelectorService.addInstance(instance) + .onSuccess(it -> context.getMonitor().info("Data plane registered to control-plane")) + .orElseThrow(f -> new EdcException("Cannot register dataplane to the controlplane: " + f.getFailureDetail())); + } + + private @NotNull Stream toTransferTypes(FlowType pull, Set types) { + return types.stream().map(it -> "%s-%s".formatted(it, pull)); + } +} diff --git a/extensions/data-plane/data-plane-self-registration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/data-plane/data-plane-self-registration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 00000000000..797302958b7 --- /dev/null +++ b/extensions/data-plane/data-plane-self-registration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,16 @@ +# +# Copyright (c) 2024 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.edc.connector.dataplane.registration.DataplaneSelfRegistrationExtension + diff --git a/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java b/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java new file mode 100644 index 00000000000..792960b2c59 --- /dev/null +++ b/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 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.edc.connector.dataplane.registration; + +import org.eclipse.edc.connector.controlplane.transfer.spi.callback.ControlApiUrl; +import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; +import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; +import org.eclipse.edc.connector.dataplane.spi.iam.PublicEndpointGeneratorService; +import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.result.ServiceResult; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(DependencyInjectionExtension.class) +class DataplaneSelfRegistrationExtensionTest { + + private final DataPlaneSelectorService dataPlaneSelectorService = mock(); + private final ControlApiUrl controlApiUrl = mock(); + private final PipelineService pipelineService = mock(); + private final PublicEndpointGeneratorService publicEndpointGeneratorService = mock(); + + @BeforeEach + void setUp(ServiceExtensionContext context) { + context.registerService(DataPlaneSelectorService.class, dataPlaneSelectorService); + context.registerService(ControlApiUrl.class, controlApiUrl); + context.registerService(PipelineService.class, pipelineService); + context.registerService(PublicEndpointGeneratorService.class, publicEndpointGeneratorService); + } + + @Test + void shouldRegisterInstanceAtStartup(DataplaneSelfRegistrationExtension extension, ServiceExtensionContext context) throws MalformedURLException { + when(context.getRuntimeId()).thenReturn("runtimeId"); + when(controlApiUrl.get()).thenReturn(URI.create("http://control/api/url")); + when(pipelineService.supportedSinkTypes()).thenReturn(Set.of("sinkType", "anotherSinkType")); + when(pipelineService.supportedSourceTypes()).thenReturn(Set.of("sourceType", "anotherSourceType")); + when(publicEndpointGeneratorService.supportedDestinationTypes()).thenReturn(Set.of("pullDestType", "anotherPullDestType")); + when(dataPlaneSelectorService.addInstance(any())).thenReturn(ServiceResult.success()); + + extension.initialize(context); + extension.start(); + + var captor = ArgumentCaptor.forClass(DataPlaneInstance.class); + verify(dataPlaneSelectorService).addInstance(captor.capture()); + var dataPlaneInstance = captor.getValue(); + assertThat(dataPlaneInstance.getId()).isEqualTo("runtimeId"); + assertThat(dataPlaneInstance.getUrl()).isEqualTo(new URL("http://control/api/url/v1/dataflows")); + assertThat(dataPlaneInstance.getAllowedSourceTypes()).containsExactlyInAnyOrder("sourceType", "anotherSourceType"); + assertThat(dataPlaneInstance.getAllowedDestTypes()).containsExactlyInAnyOrder("sinkType", "anotherSinkType"); + assertThat(dataPlaneInstance.getAllowedTransferTypes()) + .containsExactlyInAnyOrder("pullDestType-PULL", "anotherPullDestType-PULL", "sinkType-PUSH", "anotherSinkType-PUSH"); + } + + @Test + void shouldNotStart_whenRegistrationFails(DataplaneSelfRegistrationExtension extension, ServiceExtensionContext context) { + when(controlApiUrl.get()).thenReturn(URI.create("http://control/api/url")); + when(dataPlaneSelectorService.addInstance(any())).thenReturn(ServiceResult.conflict("cannot register")); + + extension.initialize(context); + + assertThatThrownBy(extension::start).isInstanceOf(EdcException.class); + } +} diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/build.gradle.kts b/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/build.gradle.kts index b7296173345..b1f46c24722 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/build.gradle.kts +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/build.gradle.kts @@ -15,7 +15,7 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + id(libs.plugins.swagger.get().pluginId) } dependencies { diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java index 2060d8642bd..9bd5ee3cb4d 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java @@ -14,6 +14,7 @@ package org.eclipse.edc.connector.dataplane.api; +import org.eclipse.edc.connector.api.control.configuration.ControlApiConfiguration; import org.eclipse.edc.connector.api.signaling.configuration.SignalingApiConfiguration; import org.eclipse.edc.connector.dataplane.api.controller.v1.DataPlaneSignalingApiController; import org.eclipse.edc.connector.dataplane.spi.manager.DataPlaneManager; @@ -33,7 +34,9 @@ public class DataPlaneSignalingApiExtension implements ServiceExtension { @Inject private WebService webService; @Inject - private SignalingApiConfiguration controlApiConfiguration; + private SignalingApiConfiguration signalingApiConfiguration; + @Inject + private ControlApiConfiguration controlApiConfiguration; @Inject private TypeTransformerRegistry transformerRegistry; @Inject @@ -49,6 +52,7 @@ public void initialize(ServiceExtensionContext context) { var signalingApiTypeTransformerRegistry = transformerRegistry.forContext("signaling-api"); var controller = new DataPlaneSignalingApiController(signalingApiTypeTransformerRegistry, dataPlaneManager, context.getMonitor().withPrefix("SignalingAPI")); + webService.registerResource(signalingApiConfiguration.getContextAlias(), controller); webService.registerResource(controlApiConfiguration.getContextAlias(), controller); } } diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-transform/src/main/java/org/eclipse/edc/connector/api/signaling/transform/from/JsonObjectFromDataFlowStartMessageTransformer.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-transform/src/main/java/org/eclipse/edc/connector/api/signaling/transform/from/JsonObjectFromDataFlowStartMessageTransformer.java index 4c74f83e776..f8e26cc22ee 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-transform/src/main/java/org/eclipse/edc/connector/api/signaling/transform/from/JsonObjectFromDataFlowStartMessageTransformer.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-transform/src/main/java/org/eclipse/edc/connector/api/signaling/transform/from/JsonObjectFromDataFlowStartMessageTransformer.java @@ -52,7 +52,7 @@ public JsonObjectFromDataFlowStartMessageTransformer(JsonBuilderFactory jsonFact public @Nullable JsonObject transform(@NotNull DataFlowStartMessage message, @NotNull TransformerContext context) { var propertiesBuilder = jsonFactory.createObjectBuilder(); transformProperties(message.getProperties(), propertiesBuilder, mapper, context); - return jsonFactory.createObjectBuilder() + var builder = jsonFactory.createObjectBuilder() .add(TYPE, EDC_DATA_FLOW_START_MESSAGE_TYPE) .add(EDC_DATA_FLOW_START_MESSAGE_FLOW_TYPE, message.getFlowType().toString()) .add(EDC_DATA_FLOW_START_MESSAGE_AGREEMENT_ID, message.getAgreementId()) @@ -60,9 +60,13 @@ public JsonObjectFromDataFlowStartMessageTransformer(JsonBuilderFactory jsonFact .add(EDC_DATA_FLOW_START_MESSAGE_DATASET_ID, message.getAssetId()) .add(EDC_DATA_FLOW_START_MESSAGE_PROPERTIES, propertiesBuilder) .add(EDC_DATA_FLOW_START_MESSAGE_DESTINATION_CALLBACK_ADDRESS, message.getCallbackAddress().toString()) - .add(EDC_DATA_FLOW_START_MESSAGE_DESTINATION_DATA_ADDRESS, context.transform(message.getDestinationDataAddress(), JsonObject.class)) .add(EDC_DATA_FLOW_START_MESSAGE_SOURCE_DATA_ADDRESS, context.transform(message.getSourceDataAddress(), JsonObject.class)) - .add(EDC_DATA_FLOW_START_MESSAGE_PARTICIPANT_ID, message.getParticipantId()) - .build(); + .add(EDC_DATA_FLOW_START_MESSAGE_PARTICIPANT_ID, message.getParticipantId()); + + if (message.getDestinationDataAddress() != null) { + builder.add(EDC_DATA_FLOW_START_MESSAGE_DESTINATION_DATA_ADDRESS, context.transform(message.getDestinationDataAddress(), JsonObject.class)); + } + + return builder.build(); } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dea4cc05f30..2d5533fa8f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ opentelemetry-proto = "1.3.1-alpha" postgres = "42.7.3" restAssured = "5.4.0" rsApi = "4.0.0" -swagger-annotations-jakarta = "2.2.21" +swagger = "2.2.21" titanium = "1.4.0" kafkaClients = "3.7.0" testcontainers = "1.19.8" @@ -82,7 +82,7 @@ opentelemetry-api = { module = "io.opentelemetry:opentelemetry-api", version.ref opentelemetry-instrumentation-annotations = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations", version.ref = "opentelemetry" } opentelemetry-proto = { module = "io.opentelemetry.proto:opentelemetry-proto", version.ref = "opentelemetry-proto" } restAssured = { module = "io.rest-assured:rest-assured", version.ref = "restAssured" } -swagger-annotations-jakarta = { module = "io.swagger.core.v3:swagger-annotations-jakarta", version.ref = "swagger-annotations-jakarta" } +swagger-annotations-jakarta = { module = "io.swagger.core.v3:swagger-annotations-jakarta", version.ref = "swagger" } titaniumJsonLd = { module = "com.apicatalog:titanium-json-ld", version.ref = "titanium" } testcontainers-junit = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" } testcontainers-kafka = { module = "org.testcontainers:kafka", version.ref = "testcontainers" } @@ -107,3 +107,4 @@ jupiter = ["junit-jupiter-api", "junit-jupiter-params"] [plugins] shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } +swagger = { id = "io.swagger.core.v3.swagger-gradle-plugin", version.ref = "swagger" } diff --git a/settings.gradle.kts b/settings.gradle.kts index ebc87c8f8fa..fac4a799a55 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -190,6 +190,7 @@ include(":extensions:control-plane:edr:edr-store-receiver") include(":extensions:data-plane:data-plane-client") include(":extensions:data-plane:data-plane-client-embedded") include(":extensions:data-plane:data-plane-control-api") +include(":extensions:data-plane:data-plane-self-registration") include(":extensions:data-plane:data-plane-signaling:data-plane-signaling-api") include(":extensions:data-plane:data-plane-signaling:data-plane-signaling-api-configuration") include(":extensions:data-plane:data-plane-signaling:data-plane-signaling-client") @@ -207,6 +208,7 @@ include(":extensions:data-plane:data-plane-kafka") include(":extensions:data-plane-selector:data-plane-selector-api") include(":extensions:data-plane-selector:data-plane-selector-client") +include(":extensions:data-plane-selector:data-plane-selector-control-api") include(":extensions:data-plane-selector:store:sql:data-plane-instance-store-sql") include(":extensions:policy-monitor:store:sql:policy-monitor-store-sql") diff --git a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/transfer/DataFlowStartMessage.java b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/transfer/DataFlowStartMessage.java index acdc5234182..0ef9409b849 100644 --- a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/transfer/DataFlowStartMessage.java +++ b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/transfer/DataFlowStartMessage.java @@ -103,7 +103,6 @@ public FlowType getFlowType() { return flowType; } - /** * The agreement id associated to the request */ @@ -247,7 +246,6 @@ public DataFlowStartMessage build() { } Objects.requireNonNull(request.processId, "processId"); Objects.requireNonNull(request.sourceDataAddress, "sourceDataAddress"); - Objects.requireNonNull(request.destinationDataAddress, "destinationDataAddress"); Objects.requireNonNull(request.traceContext, "traceContext"); Objects.requireNonNull(request.flowType, "flowType"); return request; diff --git a/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/DataPlaneSelectorService.java b/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/DataPlaneSelectorService.java index dbd50dddab0..c5579622e56 100644 --- a/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/DataPlaneSelectorService.java +++ b/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/DataPlaneSelectorService.java @@ -28,6 +28,8 @@ @ExtensionPoint public interface DataPlaneSelectorService { + String DEFAULT_STRATEGY = "random"; + /** * Returns all {@link DataPlaneInstance}s known in the system */ @@ -36,7 +38,10 @@ public interface DataPlaneSelectorService { /** * Selects the {@link DataPlaneInstance} that can handle a source and destination {@link DataAddress} using the configured * strategy. + * + * @deprecated please use the one that passes the transferType */ + @Deprecated(since = "0.6.3") default DataPlaneInstance select(DataAddress source, DataAddress destination) { return select(source, destination, "random"); } @@ -44,7 +49,10 @@ default DataPlaneInstance select(DataAddress source, DataAddress destination) { /** * Selects the {@link DataPlaneInstance} that can handle a source and destination {@link DataAddress} using the passed * strategy. + * + * @deprecated please use the one that passes the transferType */ + @Deprecated(since = "0.6.3") default DataPlaneInstance select(DataAddress source, DataAddress destination, String selectionStrategy) { return select(source, destination, selectionStrategy, null); } @@ -53,7 +61,7 @@ default DataPlaneInstance select(DataAddress source, DataAddress destination, St * Selects the {@link DataPlaneInstance} that can handle a source and destination {@link DataAddress} using the passed * strategy and the optional transferType. */ - DataPlaneInstance select(DataAddress source, DataAddress destination, String selectionStrategy, @Nullable String transferType); + DataPlaneInstance select(DataAddress source, DataAddress destination, @Nullable String selectionStrategy, @Nullable String transferType); /** diff --git a/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstance.java b/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstance.java index 7eba6431e3b..c8c46ad7ac8 100644 --- a/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstance.java +++ b/spi/data-plane-selector/data-plane-selector-spi/src/main/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstance.java @@ -28,7 +28,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -41,12 +40,12 @@ public class DataPlaneInstance { public static final String DATAPLANE_INSTANCE_TYPE = EDC_NAMESPACE + "DataPlaneInstance"; + @Deprecated(since = "0.6.3") public static final String TURN_COUNT = EDC_NAMESPACE + "turnCount"; public static final String LAST_ACTIVE = EDC_NAMESPACE + "lastActive"; public static final String URL = EDC_NAMESPACE + "url"; public static final String PROPERTIES = EDC_NAMESPACE + "properties"; public static final String ALLOWED_TRANSFER_TYPES = EDC_NAMESPACE + "allowedTransferTypes"; - public static final String ALLOWED_SOURCE_TYPES = EDC_NAMESPACE + "allowedSourceTypes"; public static final String ALLOWED_DEST_TYPES = EDC_NAMESPACE + "allowedDestTypes"; @@ -54,6 +53,7 @@ public class DataPlaneInstance { private Set allowedTransferTypes = new HashSet<>(); private Set allowedSourceTypes = new HashSet<>(); private Set allowedDestTypes = new HashSet<>(); + @Deprecated(since = "0.6.3") private int turnCount = 0; private long lastActive = Instant.now().toEpochMilli(); private URL url; @@ -67,36 +67,24 @@ public String getId() { } /** - * Determines whether this instance can handle a particular source and data address, by evaluating {@link DataAddress#getType()} - * against an internal list of allowed source and dest types and if present that the transferType is handled + * Determines whether this instance can handle a particular source and data address, by evaluating sourceAddress and + * transferType against an internal list of allowed source and transfer types. * - * @param sourceAddress The location where the data is located - * @param destinationAddress The destination address of the data + * @param sourceAddress the sourceAddress + * @param transferType the transferType * @return true if it can handle, false otherwise. */ - public boolean canHandle(DataAddress sourceAddress, DataAddress destinationAddress, @Nullable String transferType) { + public boolean canHandle(DataAddress sourceAddress, @Nullable String transferType) { Objects.requireNonNull(sourceAddress, "source cannot be null!"); - Objects.requireNonNull(destinationAddress, "destination cannot be null"); - return allowedSourceTypes.contains(sourceAddress.getType()) && allowedDestTypes.contains(destinationAddress.getType()) && - Optional.ofNullable(transferType).map(t -> allowedTransferTypes.contains(t)).orElse(true); - } - - /** - * Determines whether this instance can handle a particular source and data address, by evaluating {@link DataAddress#getType()} - * against an internal list of allowed source and dest types. - * - * @param sourceAddress The location where the data is located - * @param destinationAddress The destination address of the data - * @return true if it can handle, false otherwise. - */ - public boolean canHandle(DataAddress sourceAddress, DataAddress destinationAddress) { - return canHandle(sourceAddress, destinationAddress, null); + Objects.requireNonNull(transferType, "transferType cannot be null!"); + return allowedSourceTypes.contains(sourceAddress.getType()) && allowedTransferTypes.contains(transferType); } public URL getUrl() { return url; } + @Deprecated(since = "0.6.3") public int getTurnCount() { return turnCount; } @@ -134,6 +122,7 @@ public static Builder newInstance() { return new Builder(); } + @Deprecated(since = "0.6.3") public Builder turnCount(int turnCount) { instance.turnCount = turnCount; return this; diff --git a/spi/data-plane-selector/data-plane-selector-spi/src/test/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstanceTest.java b/spi/data-plane-selector/data-plane-selector-spi/src/test/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstanceTest.java index fd44b697dc9..ad4871b6c53 100644 --- a/spi/data-plane-selector/data-plane-selector-spi/src/test/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstanceTest.java +++ b/spi/data-plane-selector/data-plane-selector-spi/src/test/java/org/eclipse/edc/connector/dataplane/selector/spi/instance/DataPlaneInstanceTest.java @@ -66,37 +66,10 @@ void verifySerialization() throws MalformedURLException, JsonProcessingException assertThat(deserializedItf).usingRecursiveComparison().isEqualTo(inst); } - @Test - void verifyCanHandle() throws MalformedURLException { - var srcType1 = "srcType1"; - var srcType2 = "srcType1"; - var destType1 = "destType1"; - var destType2 = "destType2"; - - var inst = DataPlaneInstance.Builder.newInstance() - .id("test-id") - .url(new URL("http://localhost:8234/some/path")) - .allowedSourceType(srcType1) - .allowedSourceType(srcType2) - .allowedDestType(destType1) - .allowedDestType(destType2) - .build(); - - assertThat(inst.canHandle(createAddress(srcType1), createAddress(destType1))).isTrue(); - assertThat(inst.canHandle(createAddress(srcType1), createAddress(destType2))).isTrue(); - assertThat(inst.canHandle(createAddress(srcType2), createAddress(destType2))).isTrue(); - assertThat(inst.canHandle(createAddress(srcType2), createAddress(destType1))).isTrue(); - assertThat(inst.canHandle(createAddress(srcType2), createAddress("notexist"))).isFalse(); - assertThat(inst.canHandle(createAddress("notexist"), createAddress(destType1))).isFalse(); - - } - @Test void verifyCanHandle_withTransferType() throws MalformedURLException { var srcType1 = "srcType1"; var srcType2 = "srcType1"; - var destType1 = "destType1"; - var destType2 = "destType2"; var transferType1 = "customTransferType1"; var transferType2 = "customTransferType2"; @@ -105,19 +78,15 @@ void verifyCanHandle_withTransferType() throws MalformedURLException { .url(new URL("http://localhost:8234/some/path")) .allowedSourceType(srcType1) .allowedSourceType(srcType2) - .allowedDestType(destType1) - .allowedDestType(destType2) .allowedTransferType(transferType1) .allowedTransferType(transferType2) .build(); - assertThat(inst.canHandle(createAddress(srcType1), createAddress(destType1), transferType1)).isTrue(); - assertThat(inst.canHandle(createAddress(srcType1), createAddress(destType2), transferType1)).isTrue(); - assertThat(inst.canHandle(createAddress(srcType2), createAddress(destType2), transferType2)).isTrue(); - assertThat(inst.canHandle(createAddress(srcType2), createAddress(destType1), transferType2)).isTrue(); - assertThat(inst.canHandle(createAddress(srcType2), createAddress("notexist"))).isFalse(); - assertThat(inst.canHandle(createAddress("notexist"), createAddress(destType1))).isFalse(); - assertThat(inst.canHandle(createAddress(srcType1), createAddress(destType1), "notexist")).isFalse(); + assertThat(inst.canHandle(createAddress(srcType1), transferType1)).isTrue(); + assertThat(inst.canHandle(createAddress(srcType1), transferType1)).isTrue(); + assertThat(inst.canHandle(createAddress(srcType2), transferType2)).isTrue(); + assertThat(inst.canHandle(createAddress(srcType2), transferType2)).isTrue(); + assertThat(inst.canHandle(createAddress(srcType1), "notexist")).isFalse(); } diff --git a/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/iam/PublicEndpointGeneratorService.java b/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/iam/PublicEndpointGeneratorService.java index 5cabc84112e..34ea55889b8 100644 --- a/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/iam/PublicEndpointGeneratorService.java +++ b/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/iam/PublicEndpointGeneratorService.java @@ -18,6 +18,7 @@ import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.types.domain.DataAddress; +import java.util.Set; import java.util.function.Function; /** @@ -41,4 +42,11 @@ public interface PublicEndpointGeneratorService { * @param generatorFunction the generator function */ void addGeneratorFunction(String destinationType, Function generatorFunction); + + /** + * Return the supported destination types. + * + * @return the supported types; + */ + Set supportedDestinationTypes(); } diff --git a/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/pipeline/PipelineService.java b/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/pipeline/PipelineService.java index 38a17d696d1..63472dabfb4 100644 --- a/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/pipeline/PipelineService.java +++ b/spi/data-plane/data-plane-spi/src/main/java/org/eclipse/edc/connector/dataplane/spi/pipeline/PipelineService.java @@ -16,6 +16,8 @@ import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; +import java.util.Set; + /** * Transfers data from a {@link DataSource} to a {@link DataSink} using Data Plane extensions. * Represent the default {@link TransferService} that leverages on the internal Data-Plane transfer mechanism. @@ -33,4 +35,18 @@ public interface PipelineService extends TransferService { */ void registerFactory(DataSinkFactory factory); + /** + * Return a collection of source DataAddress types supported. + * + * @return set of types. + */ + Set supportedSourceTypes(); + + /** + * Return a collection of sink DataAddress types supported. + * + * @return set of types. + */ + Set supportedSinkTypes(); + } diff --git a/system-tests/e2e-transfer-test/control-plane/build.gradle.kts b/system-tests/e2e-transfer-test/control-plane/build.gradle.kts index 24884e095bb..f9f6d4bc3d9 100644 --- a/system-tests/e2e-transfer-test/control-plane/build.gradle.kts +++ b/system-tests/e2e-transfer-test/control-plane/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { implementation(project(":core:data-plane-selector:data-plane-selector-core")) implementation(project(":extensions:data-plane-selector:data-plane-selector-api")) + implementation(project(":extensions:data-plane-selector:data-plane-selector-control-api")) implementation(project(":extensions:control-plane:provision:provision-http")) implementation(project(":extensions:control-plane:transfer:transfer-pull-http-receiver")) diff --git a/system-tests/e2e-transfer-test/data-plane/build.gradle.kts b/system-tests/e2e-transfer-test/data-plane/build.gradle.kts index 008f40061a4..bd1207165fc 100644 --- a/system-tests/e2e-transfer-test/data-plane/build.gradle.kts +++ b/system-tests/e2e-transfer-test/data-plane/build.gradle.kts @@ -19,6 +19,7 @@ plugins { dependencies { implementation(project(":core:data-plane:data-plane-core")) implementation(project(":extensions:control-plane:api:control-plane-api-client")) + implementation(project(":extensions:data-plane:data-plane-self-registration")) implementation(project(":extensions:data-plane:data-plane-http")) implementation(project(":extensions:data-plane:data-plane-kafka")) implementation(project(":extensions:data-plane:data-plane-http-oauth2")) diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java index 8d4253f4c8c..f4fa89dff09 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java @@ -37,17 +37,19 @@ static EdcRuntimeExtension controlPlane(String name, Map configu static EdcRuntimeExtension controlPlaneEmbeddedDataPlane(String name, Map configuration) { return new EdcRuntimeExtension(name, configuration, - ":system-tests:e2e-transfer-test:control-plane", - ":extensions:control-plane:transfer:transfer-data-plane-signaling", - ":system-tests:e2e-transfer-test:data-plane", - ":extensions:data-plane:data-plane-public-api-v2" + ":system-tests:e2e-transfer-test:control-plane", + ":system-tests:e2e-transfer-test:data-plane", + ":extensions:control-plane:transfer:transfer-data-plane-signaling", + ":extensions:data-plane:data-plane-self-registration", + ":extensions:data-plane:data-plane-public-api-v2" ); } static EdcRuntimeExtension dataPlane(String name, Map configuration) { return new EdcRuntimeExtension(name, configuration, ":system-tests:e2e-transfer-test:data-plane", - ":extensions:data-plane:data-plane-public-api-v2" + ":extensions:data-plane:data-plane-public-api-v2", + ":extensions:data-plane-selector:data-plane-selector-client" ); } } @@ -77,7 +79,8 @@ static EdcRuntimeExtension dataPlane(String name, Map configurat ":extensions:data-plane:store:sql:data-plane-store-sql", ":extensions:common:sql:sql-pool:sql-pool-apache-commons", ":extensions:common:transaction:transaction-local", - ":extensions:data-plane:data-plane-public-api-v2" + ":extensions:data-plane:data-plane-public-api-v2", + ":extensions:data-plane-selector:data-plane-selector-client" ); } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java index 0dea2238bcd..1517b02835c 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java @@ -72,7 +72,10 @@ public URI backendService() { /** * Register a data plane using with input transfer type using the data plane signaling API url + * + * @deprecated dataplane now can register itself. */ + @Deprecated(since = "0.6.3") public void registerDataPlane(Set transferTypes) { registerDataPlane(dataPlaneSignaling + "/v1/dataflows", Set.of("HttpData", "HttpProvision", "Kafka"), Set.of("HttpData", "HttpProvision", "HttpProxy", "Kafka"), transferTypes); } @@ -84,7 +87,9 @@ public void registerDataPlane(Set transferTypes) { * @param sources The allowed source types * @param destinations The allowed destination types * @param transferTypes The allowed transfer types + * @deprecated dataplane now can register itself. */ + @Deprecated(since = "0.6.3") public void registerDataPlane(String url, Set sources, Set destinations, Set transferTypes) { var jsonObject = Json.createObjectBuilder() .add(CONTEXT, createObjectBuilder().add(EDC_PREFIX, EDC_NAMESPACE)) @@ -164,6 +169,7 @@ public Map dataPlaneConfiguration() { put("edc.transfer.proxy.token.signer.privatekey.alias", "1"); put("edc.transfer.proxy.token.verifier.publickey.alias", "public-key"); put("edc.dataplane.http.sink.partition.size", "1"); + put("edc.dpf.selector.url", controlPlaneControl + "/v1/dataplanes"); } }; } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndTestBase.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndTestBase.java index b5d0f54d65c..e183a37bb67 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndTestBase.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndTestBase.java @@ -18,7 +18,6 @@ import java.time.Duration; import java.util.Map; -import java.util.Set; import java.util.UUID; import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; @@ -43,8 +42,4 @@ protected void createResourcesOnProvider(String assetId, JsonObject contractPoli PROVIDER.createContractDefinition(assetId, UUID.randomUUID().toString(), accessPolicyId, contractPolicyId); } - protected void registerDataPlanes() { - PROVIDER.registerDataPlane(Set.of("HttpData-PUSH", "HttpData-PULL")); - } - } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java index 80d06857a22..ea0b372c9ba 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java @@ -80,8 +80,8 @@ class InMemory extends Tests { static final EdcClassRuntimesExtension RUNTIMES = new EdcClassRuntimesExtension( Runtimes.InMemory.controlPlane("consumer-control-plane", CONSUMER.controlPlaneConfiguration()), backendService("consumer-backend-service", CONSUMER.backendServiceConfiguration()), - Runtimes.InMemory.dataPlane("provider-data-plane", PROVIDER.dataPlaneConfiguration()), Runtimes.InMemory.controlPlane("provider-control-plane", PROVIDER.controlPlaneConfiguration()), + Runtimes.InMemory.dataPlane("provider-data-plane", PROVIDER.dataPlaneConfiguration()), backendService("provider-backend-service", PROVIDER.backendServiceConfiguration()) ); @@ -115,8 +115,8 @@ class Postgres extends Tests { static final EdcClassRuntimesExtension RUNTIMES = new EdcClassRuntimesExtension( Runtimes.Postgres.controlPlane("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration()), backendService("consumer-backend-service", CONSUMER.backendServiceConfiguration()), - Runtimes.Postgres.dataPlane("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration()), Runtimes.Postgres.controlPlane("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration()), + Runtimes.Postgres.dataPlane("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration()), backendService("provider-backend-service", PROVIDER.backendServiceConfiguration()) ); } @@ -129,7 +129,6 @@ abstract static class Tests extends TransferEndToEndTestBase { @BeforeEach void beforeEach() { - registerDataPlanes(); callbacksEndpoint = startClientAndServer(CALLBACK_PORT); } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java index 529d4eff866..77bdd7ab728 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java @@ -20,7 +20,6 @@ import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.junit.extensions.EdcClassRuntimesExtension; import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -57,8 +56,8 @@ class InMemory extends Tests { static final EdcClassRuntimesExtension RUNTIMES = new EdcClassRuntimesExtension( controlPlane("consumer-control-plane", CONSUMER.controlPlaneConfiguration()), backendService("consumer-backend-service", CONSUMER.backendServiceConfiguration()), - dataPlane("provider-data-plane", PROVIDER.dataPlaneConfiguration()), controlPlane("provider-control-plane", PROVIDER.controlPlaneConfiguration()), + dataPlane("provider-data-plane", PROVIDER.dataPlaneConfiguration()), backendService("provider-backend-service", PROVIDER.backendServiceConfiguration()) ); @@ -92,19 +91,14 @@ class Postgres extends Tests { static final EdcClassRuntimesExtension RUNTIMES = new EdcClassRuntimesExtension( Runtimes.Postgres.controlPlane("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration()), backendService("consumer-backend-service", CONSUMER.backendServiceConfiguration()), - Runtimes.Postgres.dataPlane("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration()), Runtimes.Postgres.controlPlane("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration()), + Runtimes.Postgres.dataPlane("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration()), backendService("provider-backend-service", PROVIDER.backendServiceConfiguration()) ); } abstract static class Tests extends TransferEndToEndTestBase { - @BeforeEach - void beforeEach() { - registerDataPlanes(); - } - @Test void httpPushDataTransfer() { var assetId = UUID.randomUUID().toString(); diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java index 22dbbbc5be1..06307cb72cb 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java @@ -43,7 +43,6 @@ import java.util.Map; import java.util.Objects; import java.util.Properties; -import java.util.Set; import java.util.UUID; import javax.validation.constraints.NotNull; @@ -82,8 +81,8 @@ class InMemory extends Tests { static final EdcClassRuntimesExtension RUNTIMES = new EdcClassRuntimesExtension( controlPlane("consumer-control-plane", CONSUMER.controlPlaneConfiguration()), backendService("consumer-backend-service", CONSUMER.backendServiceConfiguration()), - dataPlane("provider-data-plane", PROVIDER.dataPlaneConfiguration()), controlPlane("provider-control-plane", PROVIDER.controlPlaneConfiguration()), + dataPlane("provider-data-plane", PROVIDER.dataPlaneConfiguration()), backendService("provider-backend-service", PROVIDER.backendServiceConfiguration()) ); @@ -114,7 +113,6 @@ void kafkaToHttpTransfer() { .withMethod(HttpMethod.POST.name()) .withPath("/api/service"); destinationServer.when(request).respond(response()); - PROVIDER.registerDataPlane(Set.of("HttpData-PUSH")); var assetId = UUID.randomUUID().toString(); createResourcesOnProvider(assetId, contractExpiresIn("10s"), kafkaSourceProperty()); @@ -151,8 +149,6 @@ void kafkaToKafkaTransfer() { try (var consumer = createKafkaConsumer()) { consumer.subscribe(List.of(SINK_TOPIC)); - PROVIDER.registerDataPlane(Set.of("Kafka-PUSH")); - var assetId = UUID.randomUUID().toString(); createResourcesOnProvider(assetId, contractExpiresIn("10s"), kafkaSourceProperty()); @@ -169,8 +165,6 @@ void shouldSuspendAndResumeTransfer() { try (var consumer = createKafkaConsumer()) { consumer.subscribe(List.of(SINK_TOPIC)); - PROVIDER.registerDataPlane(Set.of("Kafka-PUSH")); - var assetId = UUID.randomUUID().toString(); createResourcesOnProvider(assetId, noConstraintPolicy(), kafkaSourceProperty()); diff --git a/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/Runtimes.java b/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/Runtimes.java index fca190704db..3d589a0c3cf 100644 --- a/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/Runtimes.java +++ b/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/Runtimes.java @@ -52,6 +52,7 @@ static HashMap inMemoryConfiguration() { put("web.http.protocol.port", String.valueOf(ManagementApiEndToEndTestBase.PROTOCOL_PORT)); put("edc.dsp.callback.address", "http://localhost:" + ManagementApiEndToEndTestBase.PROTOCOL_PORT + "/protocol"); put("web.http.port", String.valueOf(getFreePort())); + put("web.http.control.port", String.valueOf(getFreePort())); put("web.http.management.path", "/management"); put("web.http.management.port", String.valueOf(ManagementApiEndToEndTestBase.PORT)); } diff --git a/system-tests/telemetry/telemetry-test-runner/src/test/java/org/eclipse/edc/test/e2e/tracing/BaseTelemetryEndToEndTest.java b/system-tests/telemetry/telemetry-test-runner/src/test/java/org/eclipse/edc/test/e2e/tracing/BaseTelemetryEndToEndTest.java index 391c35af2df..4990b78faa1 100644 --- a/system-tests/telemetry/telemetry-test-runner/src/test/java/org/eclipse/edc/test/e2e/tracing/BaseTelemetryEndToEndTest.java +++ b/system-tests/telemetry/telemetry-test-runner/src/test/java/org/eclipse/edc/test/e2e/tracing/BaseTelemetryEndToEndTest.java @@ -35,6 +35,7 @@ public abstract class BaseTelemetryEndToEndTest { { put("web.http.path", "/"); put("web.http.port", String.valueOf(DEFAULT_PORT)); + put("web.http.control.port", String.valueOf(getFreePort())); put("web.http.protocol.path", "/protocol"); put("web.http.protocol.port", String.valueOf(PROTOCOL_PORT)); put("edc.dsp.callback.address", "http://localhost:" + PROTOCOL_PORT + "/protocol");