Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: introduce PortMappingRegistry service #4677

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.PortMappingRegistry;

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 PortMappingRegistry portMappingRegistry;

@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());
portMappingRegistry.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.PortMappingRegistry;
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 PortMappingRegistry portMappingRegistry = mock();


@BeforeEach
void setUp(ServiceExtensionContext context) {
context.registerService(WebServer.class, webServer);
context.registerService(PortMappingRegistry.class, portMappingRegistry);
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(portMappingRegistry).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(portMappingRegistry).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.PortMappingRegistry;
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 PortMappingRegistry portMappingRegistry;
@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());
portMappingRegistry.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.PortMappingRegistry;
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 PortMappingRegistry portMappingRegistry = 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(PortMappingRegistry.class, portMappingRegistry);
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(portMappingRegistry).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
Loading