Skip to content

Commit

Permalink
refactor: introduce PortMappings service
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt committed Dec 16, 2024
1 parent dd54469 commit 551a4bd
Show file tree
Hide file tree
Showing 30 changed files with 546 additions and 736 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
import org.eclipse.edc.participant.spi.ParticipantIdMapper;
import org.eclipse.edc.policy.model.AtomicConstraint;
import org.eclipse.edc.policy.model.LiteralExpression;
import org.eclipse.edc.runtime.metamodel.annotation.Configuration;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provides;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.runtime.metamodel.annotation.SettingContext;
import org.eclipse.edc.runtime.metamodel.annotation.Settings;
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
import org.eclipse.edc.spi.system.Hostname;
import org.eclipse.edc.spi.system.ServiceExtension;
Expand All @@ -45,11 +46,10 @@
import org.eclipse.edc.transform.transformer.edc.to.JsonObjectToQuerySpecTransformer;
import org.eclipse.edc.transform.transformer.edc.to.JsonValueToGenericTypeTransformer;
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.ApiContext;
import org.eclipse.edc.web.spi.configuration.WebServiceConfigurer;
import org.eclipse.edc.web.spi.configuration.WebServiceSettings;
import org.eclipse.edc.web.spi.configuration.PortMapping;
import org.eclipse.edc.web.spi.configuration.PortMappings;

import java.util.Map;

Expand Down Expand Up @@ -81,32 +81,29 @@
public class DspApiConfigurationExtension implements ServiceExtension {

public static final String NAME = "Dataspace Protocol API Configuration Extension";
@SettingContext("Protocol API context setting key")
private static final String PROTOCOL_CONFIG_KEY = "web.http." + ApiContext.PROTOCOL;
public static final WebServiceSettings SETTINGS = WebServiceSettings.Builder.newInstance()
.apiConfigKey(PROTOCOL_CONFIG_KEY)
.contextAlias(ApiContext.PROTOCOL)
.defaultPath("/api/dsp")
.defaultPort(8282)
.build();

static final String DEFAULT_PROTOCOL_PATH = "/api/protocol";
static final int DEFAULT_PROTOCOL_PORT = 8282;

@Setting(description = "Configures endpoint for reaching the Protocol API in the form \"<hostname:protocol.port/protocol.path>\"", key = "edc.dsp.callback.address", required = false)
private String callbackAddress;
@Configuration
private DspApiConfiguration apiConfiguration;

@Inject
private TypeManager typeManager;
@Inject
private WebService webService;
@Inject
private WebServer webServer;
@Inject
private WebServiceConfigurer configurator;
@Inject
private JsonLd jsonLd;
@Inject
private TypeTransformerRegistry transformerRegistry;
@Inject
private ParticipantIdMapper participantIdMapper;
@Inject
private Hostname hostname;
@Inject
private PortMappings portMappings;

@Override
public String name() {
Expand All @@ -115,11 +112,10 @@ public String name() {

@Override
public void initialize(ServiceExtensionContext context) {
var contextConfig = context.getConfig(PROTOCOL_CONFIG_KEY);
var apiConfiguration = configurator.configure(contextConfig, webServer, SETTINGS);
var dspWebhookAddress = ofNullable(callbackAddress).orElseGet(() -> format("http://%s:%s%s", hostname.get(), apiConfiguration.getPort(), apiConfiguration.getPath()));

var portMapping = new PortMapping(ApiContext.PROTOCOL, apiConfiguration.port(), apiConfiguration.path());
portMappings.register(portMapping);

var dspWebhookAddress = ofNullable(callbackAddress).orElseGet(() -> format("http://%s:%s%s", hostname.get(), portMapping.port(), portMapping.path()));
context.registerService(ProtocolWebhook.class, () -> dspWebhookAddress);

var jsonLdMapper = typeManager.getMapper(JSON_LD);
Expand Down Expand Up @@ -177,7 +173,6 @@ private void registerV08Transformers(ObjectMapper mapper) {

dspApiTransformerRegistry.register(new JsonObjectFromPolicyTransformer(jsonBuilderFactory, participantIdMapper));
dspApiTransformerRegistry.register(new JsonObjectFromDataAddressDspaceTransformer(jsonBuilderFactory, mapper));

}

private void registerV2024Transformers(ObjectMapper mapper) {
Expand All @@ -188,6 +183,15 @@ private void registerV2024Transformers(ObjectMapper mapper) {

dspApiTransformerRegistry.register(new JsonObjectFromPolicyTransformer(jsonBuilderFactory, participantIdMapper, true));
dspApiTransformerRegistry.register(new JsonObjectFromDataAddressDspace2024Transformer(jsonBuilderFactory, mapper));
}

@Settings
record DspApiConfiguration(
@Setting(key = "web.http." + ApiContext.PROTOCOL + ".port", description = "Port for " + ApiContext.PROTOCOL + " api context", defaultValue = DEFAULT_PROTOCOL_PORT + "")
int port,
@Setting(key = "web.http." + ApiContext.PROTOCOL + ".path", description = "Path for " + ApiContext.PROTOCOL + " api context", defaultValue = DEFAULT_PROTOCOL_PATH)
String path
) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,14 @@
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
import org.eclipse.edc.spi.system.Hostname;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.configuration.Config;
import org.eclipse.edc.spi.system.configuration.ConfigFactory;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
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.ApiContext;
import org.eclipse.edc.web.spi.configuration.WebServiceConfiguration;
import org.eclipse.edc.web.spi.configuration.WebServiceConfigurer;
import org.eclipse.edc.web.spi.configuration.PortMapping;
import org.eclipse.edc.web.spi.configuration.PortMappings;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -46,7 +44,8 @@
import static org.eclipse.edc.jsonld.spi.Namespaces.DCT_SCHEMA;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.SETTINGS;
import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.DEFAULT_PROTOCOL_PATH;
import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.DEFAULT_PROTOCOL_PORT;
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE_V_08;
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE_V_2024_1;
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
Expand All @@ -61,30 +60,23 @@
@ExtendWith(DependencyInjectionExtension.class)
class DspApiConfigurationExtensionTest {

private final WebServiceConfigurer configurer = mock();
private final WebServer webServer = mock();
private final WebService webService = mock();
private final TypeManager typeManager = mock();
private final JsonLd jsonLd = mock();
private final PortMappings portMappings = mock();


@BeforeEach
void setUp(ServiceExtensionContext context) {
context.registerService(WebServer.class, webServer);
context.registerService(PortMappings.class, portMappings);
context.registerService(WebService.class, webService);
context.registerService(WebServiceConfigurer.class, configurer);
context.registerService(TypeManager.class, typeManager);
context.registerService(Hostname.class, () -> "hostname");
context.registerService(JsonLd.class, jsonLd);
TypeTransformerRegistry typeTransformerRegistry = mock();
when(typeTransformerRegistry.forContext(any())).thenReturn(mock());
context.registerService(TypeTransformerRegistry.class, typeTransformerRegistry);

var webServiceConfiguration = WebServiceConfiguration.Builder.newInstance()
.path("/path")
.port(1234)
.build();
when(configurer.configure(any(Config.class), any(), any())).thenReturn(webServiceConfiguration);
when(typeManager.getMapper(any())).thenReturn(mock());
}

Expand All @@ -94,8 +86,8 @@ void shouldComposeProtocolWebhook_whenNotConfigured(DspApiConfigurationExtension

extension.initialize(context);

verify(configurer).configure(any(Config.class), eq(webServer), eq(SETTINGS));
assertThat(context.getService(ProtocolWebhook.class).url()).isEqualTo("http://hostname:1234/path");
verify(portMappings).register(new PortMapping(ApiContext.PROTOCOL, DEFAULT_PROTOCOL_PORT, DEFAULT_PROTOCOL_PATH));
assertThat(context.getService(ProtocolWebhook.class).url()).isEqualTo("http://hostname:%s%s".formatted(DEFAULT_PROTOCOL_PORT, DEFAULT_PROTOCOL_PATH));
}

@Test
Expand All @@ -110,7 +102,7 @@ void shouldUseConfiguredProtocolWebhook(ServiceExtensionContext context, ObjectF

extension.initialize(context);

verify(configurer).configure(any(Config.class), eq(webServer), eq(SETTINGS));
verify(portMappings).register(new PortMapping(ApiContext.PROTOCOL, 1234, "/path"));
assertThat(context.getService(ProtocolWebhook.class).url()).isEqualTo("http://webhook");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
import org.eclipse.edc.api.auth.spi.AuthenticationRequestFilter;
import org.eclipse.edc.api.auth.spi.registry.ApiAuthenticationRegistry;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.runtime.metamodel.annotation.Configuration;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provides;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.runtime.metamodel.annotation.SettingContext;
import org.eclipse.edc.runtime.metamodel.annotation.Settings;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.system.Hostname;
import org.eclipse.edc.spi.system.ServiceExtension;
Expand All @@ -32,12 +33,10 @@
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.ApiContext;
import org.eclipse.edc.web.spi.configuration.WebServiceConfiguration;
import org.eclipse.edc.web.spi.configuration.WebServiceConfigurer;
import org.eclipse.edc.web.spi.configuration.WebServiceSettings;
import org.eclipse.edc.web.spi.configuration.PortMapping;
import org.eclipse.edc.web.spi.configuration.PortMappings;
import org.eclipse.edc.web.spi.configuration.context.ControlApiUrl;

import java.io.IOException;
Expand All @@ -64,23 +63,18 @@
public class ControlApiConfigurationExtension implements ServiceExtension {

public static final String NAME = "Control API configuration";
static final String CONTROL_SCOPE = "CONTROL_API";
static final int DEFAULT_CONTROL_PORT = 9191;
static final String DEFAULT_CONTROL_PATH = "/api/control";
private static final String API_VERSION_JSON_FILE = "control-api-version.json";

@Setting(description = "Configures endpoint for reaching the Control API. If it's missing it defaults to the hostname configuration.", key = "edc.control.endpoint", required = false)
private String controlEndpoint;
public static final String CONTROL_SCOPE = "CONTROL_API";
@SettingContext("Control API context setting key")
private static final String CONTROL_CONFIG_KEY = "web.http." + ApiContext.CONTROL;
public static final WebServiceSettings SETTINGS = WebServiceSettings.Builder.newInstance()
.apiConfigKey(CONTROL_CONFIG_KEY)
.contextAlias(ApiContext.CONTROL)
.defaultPort(9191)
.build();
private static final String API_VERSION_JSON_FILE = "control-api-version.json";
@Configuration
private ControlApiConfiguration apiConfiguration;

@Inject
private WebServer webServer;
@Inject
private WebServiceConfigurer configurator;
private PortMappings portMappings;
@Inject
private WebService webService;
@Inject
Expand All @@ -91,7 +85,6 @@ public class ControlApiConfigurationExtension implements ServiceExtension {
private TypeManager typeManager;
@Inject
private ApiAuthenticationRegistry authenticationRegistry;

@Inject
private ApiVersionService apiVersionService;

Expand All @@ -102,10 +95,10 @@ public String name() {

@Override
public void initialize(ServiceExtensionContext context) {
var config = context.getConfig(CONTROL_CONFIG_KEY);
var controlApiConfiguration = configurator.configure(config, webServer, SETTINGS);
var portMapping = new PortMapping(ApiContext.CONTROL, apiConfiguration.port(), apiConfiguration.path());
portMappings.register(portMapping);
var jsonLdMapper = typeManager.getMapper(JSON_LD);
context.registerService(ControlApiUrl.class, controlApiUrl(context, controlApiConfiguration));
context.registerService(ControlApiUrl.class, controlApiUrl(context, portMapping));

jsonLd.registerNamespace(EDC_PREFIX, EDC_NAMESPACE, CONTROL_SCOPE);
jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, CONTROL_SCOPE);
Expand Down Expand Up @@ -134,8 +127,8 @@ private void registerVersionInfo(ClassLoader resourceClassLoader) {
}
}

private ControlApiUrl controlApiUrl(ServiceExtensionContext context, WebServiceConfiguration config) {
var callbackAddress = ofNullable(controlEndpoint).orElseGet(() -> format("http://%s:%s%s", hostname.get(), config.getPort(), config.getPath()));
private ControlApiUrl controlApiUrl(ServiceExtensionContext context, PortMapping config) {
var callbackAddress = ofNullable(controlEndpoint).orElseGet(() -> format("http://%s:%s%s", hostname.get(), config.port(), config.path()));

try {
var url = URI.create(callbackAddress);
Expand All @@ -145,4 +138,14 @@ private ControlApiUrl controlApiUrl(ServiceExtensionContext context, WebServiceC
throw new EdcException(e);
}
}

@Settings
record ControlApiConfiguration(
@Setting(key = "web.http." + ApiContext.CONTROL + ".port", description = "Port for " + ApiContext.CONTROL + " api context", defaultValue = DEFAULT_CONTROL_PORT + "")
int port,
@Setting(key = "web.http." + ApiContext.CONTROL + ".path", description = "Path for " + ApiContext.CONTROL + " api context", defaultValue = DEFAULT_CONTROL_PATH)
String path
) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
import org.eclipse.edc.spi.system.configuration.ConfigFactory;
import org.eclipse.edc.spi.types.TypeManager;
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.ApiContext;
import org.eclipse.edc.web.spi.configuration.PortMapping;
import org.eclipse.edc.web.spi.configuration.PortMappings;
import org.eclipse.edc.web.spi.configuration.context.ControlApiUrl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -37,6 +38,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.CONTROL_SCOPE;
import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.DEFAULT_CONTROL_PATH;
import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.DEFAULT_CONTROL_PORT;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB;
import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_PREFIX;
import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_SCHEMA;
Expand All @@ -53,24 +56,17 @@
@ExtendWith(DependencyInjectionExtension.class)
public class ControlApiConfigurationExtensionTest {

private final WebServiceConfigurer configurator = mock();
private final PortMappings portMappings = mock();
private final WebService webService = mock();
private final JsonLd jsonLd = mock();

private final WebServiceConfiguration webServiceConfiguration = WebServiceConfiguration.Builder.newInstance()
.path("/path")
.port(1234)
.build();

@BeforeEach
void setUp(ServiceExtensionContext context) {
context.registerService(WebServiceConfigurer.class, configurator);
context.registerService(PortMappings.class, portMappings);
context.registerService(Hostname.class, () -> "hostname");
context.registerService(WebService.class, webService);
context.registerService(TypeManager.class, new JacksonTypeManager());
context.registerService(JsonLd.class, jsonLd);

when(configurator.configure(any(), any(), any())).thenReturn(webServiceConfiguration);
}

@Test
Expand All @@ -79,8 +75,9 @@ void shouldComposeControlApiUrl(ControlApiConfigurationExtension extension, Serv

extension.initialize(context);

verify(portMappings).register(new PortMapping(ApiContext.CONTROL, DEFAULT_CONTROL_PORT, DEFAULT_CONTROL_PATH));
var url = context.getService(ControlApiUrl.class);
assertThat(url.get().toString()).isEqualTo("http://hostname:1234/path");
assertThat(url.get().toString()).isEqualTo("http://hostname:%s%s".formatted(DEFAULT_CONTROL_PORT, DEFAULT_CONTROL_PATH));
}

@Test
Expand Down
Loading

0 comments on commit 551a4bd

Please sign in to comment.