diff --git a/DEPENDENCIES b/DEPENDENCIES index 09f7612cd39..128c28d0708 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -349,7 +349,7 @@ maven/mavencentral/org.testcontainers/jdbc/1.20.0, MIT, approved, clearlydefined maven/mavencentral/org.testcontainers/junit-jupiter/1.20.0, MIT, approved, clearlydefined maven/mavencentral/org.testcontainers/kafka/1.20.0, MIT, approved, clearlydefined maven/mavencentral/org.testcontainers/postgresql/1.20.0, MIT, approved, clearlydefined -maven/mavencentral/org.testcontainers/testcontainers/1.20.0, None, restricted, #15747 +maven/mavencentral/org.testcontainers/testcontainers/1.20.0, MIT, approved, #15747 maven/mavencentral/org.testcontainers/vault/1.20.0, MIT, approved, clearlydefined maven/mavencentral/org.xerial.snappy/snappy-java/1.1.10.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #9098 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined diff --git a/extensions/common/sql/sql-bootstrapper/build.gradle.kts b/extensions/common/sql/sql-bootstrapper/build.gradle.kts new file mode 100644 index 00000000000..e3b44eccb87 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * 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` + `java-test-fixtures` + `maven-publish` +} + +dependencies { + api(project(":spi:common:core-spi")) + api(project(":spi:common:transaction-spi")) + implementation(project(":spi:common:transaction-datasource-spi")) + implementation(project(":extensions:common:sql:sql-core")) // SqlQueryExecutor +// + testImplementation(project(":core:common:junit")) + testImplementation(libs.assertj) +} + + diff --git a/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/QueuedStatementRecord.java b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/QueuedStatementRecord.java new file mode 100644 index 00000000000..b99661ac6a6 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/QueuedStatementRecord.java @@ -0,0 +1,18 @@ +/* + * 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.sql.bootstrapper; + +record QueuedStatementRecord(String name, String datasourceName, String sql) { +} diff --git a/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlDmlStatementRunner.java b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlDmlStatementRunner.java new file mode 100644 index 00000000000..7397ee06156 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlDmlStatementRunner.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.sql.bootstrapper; + +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.persistence.EdcPersistenceException; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; +import org.eclipse.edc.transaction.spi.TransactionContext; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +import static org.eclipse.edc.spi.result.Result.failure; +import static org.eclipse.edc.spi.result.Result.success; + +/** + * Internal class to the SQL Bootstrapper Extension module with the intended purpose to execute a series of DML statements against + * the database. + */ +class SqlDmlStatementRunner { + + private final TransactionContext transactionContext; + private final QueryExecutor queryExecutor; + private final Monitor monitor; + private final DataSourceRegistry dataSourceRegistry; + + SqlDmlStatementRunner(TransactionContext transactionContext, QueryExecutor queryExecutor, Monitor monitor, DataSourceRegistry dataSourceRegistry) { + this.transactionContext = transactionContext; + this.queryExecutor = queryExecutor; + this.monitor = monitor; + this.dataSourceRegistry = dataSourceRegistry; + } + + /** + * Executes the queued DML statements one after the other. This method is intended to be called only from the {@link SqlSchemaBootstrapperExtension}. + * + * @param statements A map containing the datasource name as key and the SQL statements as value + * @return A summary result of all the statements. + */ + public Result executeSql(Map> statements) { + monitor.debug("Running DML statements: [%s]".formatted(String.join(", ", statements.keySet()))); + return transactionContext.execute(() -> statements.entrySet().stream() + .map(statement -> { + var connectionResult = getConnection(statement.getKey()); + return connectionResult.compose(connection -> { + try { + queryExecutor.execute(connection, String.join("", statement.getValue())); + } catch (EdcPersistenceException sqlException) { + return failure(sqlException.getMessage()); + } + return success(); + }); + }) + .reduce(Result::merge) + .orElse(Result.success())); + } + + public Result getConnection(String datasourceName) { + try { + var resolve = dataSourceRegistry.resolve(datasourceName); + return resolve != null ? success(resolve.getConnection()) : + failure("No datasource found with name '%s'".formatted(datasourceName)); + } catch (SQLException e) { + return failure(e.getMessage()); + } + } +} diff --git a/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapper.java b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapper.java new file mode 100644 index 00000000000..7d67ac6ac15 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapper.java @@ -0,0 +1,59 @@ +/* + * 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.sql.bootstrapper; + +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; + +import java.util.List; +import java.util.Map; + +/** + * Provides a convenient way to create database structures in an SQL database. DML statements can be added in the {@code initialize()} + * phase of extensions and the bootstrapper takes care of executing them against the database. + */ +public interface SqlSchemaBootstrapper { + /** + * Extensions that operate a store based on an SQL database and thus require a certain database structure to be present, + * can use this class to have their schema auto-generated. The entire DDL has to be in a file that is available from the resources. + *

+ * Note that all DDL statements must be queued during the {@link ServiceExtension#initialize(ServiceExtensionContext)} phase and + * individual statements must not rely on ordering, since that depends on extension ordering. + * + * @param datasourceName The name of the datasource against which the statements are to be run + * @param resourceName An SQL DDL statement. Cannot contain prepared statements. Do not add DML statements here! + */ + default void addStatementFromResource(String datasourceName, String resourceName) { + addStatementFromResource(datasourceName, resourceName, getClass().getClassLoader()); + } + + /** + * Extensions that operate a store based on an SQL database and thus require a certain database structure to be present, + * can use this class to have their schema auto-generated. The entire DDL has to be in a file that is available from the resources. + *

+ * Note that all DDL statements must be queued during the {@link ServiceExtension#initialize(ServiceExtensionContext)} phase and + * individual statements must not rely on ordering, since that depends on extension ordering. + * + * @param datasourceName The name of the datasource against which the statements are to be run + * @param resourceName An SQL DDL statement. Cannot contain prepared statements. Do not add DML statements here! + * @param classLoader A classloader which is used to resolve the resource + */ + void addStatementFromResource(String datasourceName, String resourceName, ClassLoader classLoader); + + /** + * Gets all registered DML statements as a map where the datasource name is the key, and the SQL statement(s) is the value. + */ + Map> getStatements(); +} diff --git a/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperExtension.java b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperExtension.java new file mode 100644 index 00000000000..6bc5ef581d1 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperExtension.java @@ -0,0 +1,72 @@ +/* + * 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.sql.bootstrapper; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.persistence.EdcPersistenceException; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; +import org.eclipse.edc.transaction.spi.TransactionContext; + +import static org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapperExtension.NAME; + +@Extension(value = NAME, categories = { "sql", "persistence", "storage" }) +public class SqlSchemaBootstrapperExtension implements ServiceExtension { + public static final String NAME = "SQL Schema Bootstrapper Extension"; + public static final String SCHEMA_AUTOCREATE_PROPERTY = "edc.sql.schema.autocreate"; + public static final boolean SCHEMA_AUTOCREATE_DEFAULT = false; + + @Inject + private TransactionContext transactionContext; + @Inject + private QueryExecutor queryExecutor; + @Inject + private DataSourceRegistry datasourceRegistry; + @Inject + private Monitor monitor; + + private SqlSchemaBootstrapperImpl bootstrapper; + private Boolean shouldAutoCreate; + + @Override + public void initialize(ServiceExtensionContext context) { + shouldAutoCreate = context.getConfig().getBoolean(SCHEMA_AUTOCREATE_PROPERTY, SCHEMA_AUTOCREATE_DEFAULT); + } + + @Override + public void prepare() { + if (shouldAutoCreate) { + var statements = getBootstrapper().getStatements(); + new SqlDmlStatementRunner(transactionContext, queryExecutor, monitor, datasourceRegistry).executeSql(statements) + .orElseThrow(f -> new EdcPersistenceException("Failed to bootstrap SQL schema, error '%s'".formatted(f.getFailureDetail()))); + + } else { + monitor.debug("Automatic SQL schema creation is disabled. To enable it, set '%s' = true".formatted(SCHEMA_AUTOCREATE_PROPERTY)); + } + } + + @Provider + public SqlSchemaBootstrapper getBootstrapper() { + if (bootstrapper == null) { + bootstrapper = new SqlSchemaBootstrapperImpl(); + } + return bootstrapper; + } +} diff --git a/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperImpl.java b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperImpl.java new file mode 100644 index 00000000000..7f7cc8f0768 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/main/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperImpl.java @@ -0,0 +1,48 @@ +/* + * 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.sql.bootstrapper; + +import org.eclipse.edc.spi.EdcException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Scanner; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toList; + +public class SqlSchemaBootstrapperImpl implements SqlSchemaBootstrapper { + + private final List statements = new ArrayList<>(); + + @Override + public void addStatementFromResource(String datasourceName, String resourceName, ClassLoader classLoader) { + try (var sqlStream = classLoader.getResourceAsStream(resourceName); var scanner = new Scanner(Objects.requireNonNull(sqlStream)).useDelimiter("\\A")) { + var sql = scanner.next(); + statements.add(new QueuedStatementRecord(resourceName, datasourceName, sql)); + } catch (IOException e) { + throw new EdcException(e); + } + } + + @Override + public Map> getStatements() { + return statements.stream().collect(groupingBy(QueuedStatementRecord::datasourceName, mapping(QueuedStatementRecord::sql, toList()))); + } +} diff --git a/extensions/common/sql/sql-bootstrapper/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/extensions/common/sql/sql-bootstrapper/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 00000000000..a0d446863f6 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,15 @@ +# +# 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.sql.bootstrapper.SqlSchemaBootstrapperExtension \ No newline at end of file diff --git a/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlDmlStatementRunnerTest.java b/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlDmlStatementRunnerTest.java new file mode 100644 index 00000000000..8a94acfba7f --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlDmlStatementRunnerTest.java @@ -0,0 +1,100 @@ +/* + * 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.sql.bootstrapper; + +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; +import org.eclipse.edc.transaction.spi.NoopTransactionContext; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.notNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +class SqlDmlStatementRunnerTest { + private final QueryExecutor queryExecutor = mock(); + private final DataSourceRegistry datasourceRegistry = mock(); + private final SqlDmlStatementRunner executor = new SqlDmlStatementRunner(new NoopTransactionContext(), queryExecutor, mock(), datasourceRegistry); + + + @Test + void executeSql() throws SQLException { + var dataSourceMock = mock(DataSource.class); + when(dataSourceMock.getConnection()).thenReturn(mock(Connection.class)); + when(datasourceRegistry.resolve(anyString())).thenReturn(dataSourceMock); + + executor.executeSql(Map.of("foosource", List.of("test-schema.sql"))); + + verify(queryExecutor).execute(any(Connection.class), notNull()); + } + + @Test + void executeSql_errorDuringGetConnection() throws SQLException { + var dataSourceMock = mock(DataSource.class); + when(dataSourceMock.getConnection()).thenThrow(new SQLException("test exception")); + when(datasourceRegistry.resolve(anyString())).thenReturn(dataSourceMock); + + assertThat(executor.executeSql(Map.of("foosource", List.of("test-schema.sql")))).isFailed() + .detail().isEqualTo("test exception"); + + verifyNoInteractions(queryExecutor); + } + + @Test + void executeSql_datasourceNotFound() { + when(datasourceRegistry.resolve(anyString())).thenReturn(null); + assertThat(executor.executeSql(Map.of("foosource", List.of("test-schema.sql")))).isFailed() + .detail().isEqualTo("No datasource found with name 'foosource'"); + + verifyNoInteractions(queryExecutor); + } + + @Test + void executeSql_noStatementsInQueue() { + executor.executeSql(Map.of()); + verifyNoInteractions(queryExecutor, datasourceRegistry); + } + + @Test + void executeSql_oneStatementFails() throws SQLException { + var dataSourceMock = mock(DataSource.class); + when(dataSourceMock.getConnection()).thenReturn(mock(Connection.class)); + when(datasourceRegistry.resolve(anyString())).thenReturn(dataSourceMock); + + when(queryExecutor.execute(any(Connection.class), notNull())) + .thenReturn(1) + .thenThrow(new EdcException("test exception")); + + assertThatThrownBy(() -> executor.executeSql(Map.of("foosource", List.of("test-schema.sql"), "barsource", List.of("test-schema.sql")))) + .isInstanceOf(EdcException.class) + .hasMessage("test exception"); + + verify(queryExecutor, times(2)).execute(any(Connection.class), notNull()); + } +} \ No newline at end of file diff --git a/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperExtensionTest.java b/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperExtensionTest.java new file mode 100644 index 00000000000..a0dc78cbd53 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperExtensionTest.java @@ -0,0 +1,72 @@ +/* + * 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.sql.bootstrapper; + +import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.Config; +import org.eclipse.edc.transaction.spi.TransactionContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapperExtension.SCHEMA_AUTOCREATE_PROPERTY; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ComponentTest +@ExtendWith(DependencyInjectionExtension.class) +class SqlSchemaBootstrapperExtensionTest { + + private final TransactionContext transactionContext = mock(); + + @BeforeEach + void setUp(ServiceExtensionContext context) { + context.registerService(TransactionContext.class, transactionContext); + } + + @Test + void prepare_autocreateDisabled(SqlSchemaBootstrapperExtension extension, ServiceExtensionContext context) { + var config = mock(Config.class); + when(config.getBoolean(eq("edc.sql.schema.autocreate"), anyBoolean())).thenReturn(false); + when(context.getConfig()).thenReturn(config); + extension.initialize(context); + extension.prepare(); + verifyNoInteractions(transactionContext); + } + + @Test + void prepare(SqlSchemaBootstrapperExtension extension, ServiceExtensionContext context) { + var config = mock(Config.class); + when(config.getBoolean(eq(SCHEMA_AUTOCREATE_PROPERTY), anyBoolean())).thenReturn(true); + when(context.getConfig()).thenReturn(config); + when(transactionContext.execute(isA(TransactionContext.ResultTransactionBlock.class))) + .thenReturn(Result.success("foobar")); + + extension.initialize(context); + + assertThatNoException().isThrownBy(extension::prepare); + verify(transactionContext).execute(isA(TransactionContext.ResultTransactionBlock.class)); + } + +} \ No newline at end of file diff --git a/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperImplTest.java b/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperImplTest.java new file mode 100644 index 00000000000..4b0ecad57c4 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/test/java/org/eclipse/edc/sql/bootstrapper/SqlSchemaBootstrapperImplTest.java @@ -0,0 +1,39 @@ +/* + * 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.sql.bootstrapper; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class SqlSchemaBootstrapperImplTest { + + + private final SqlSchemaBootstrapperImpl bootstrapper = new SqlSchemaBootstrapperImpl(); + + @Test + void addStatementFromResource() { + assertThatNoException().isThrownBy(() -> bootstrapper.addStatementFromResource("foosource", "test-schema.sql")); + } + + @Test + void addStatementFromResource_resourceNotFound() { + assertThatThrownBy(() -> bootstrapper.addStatementFromResource("foosource", "nonexist.sql")) + .isInstanceOf(NullPointerException.class); + } + + +} \ No newline at end of file diff --git a/extensions/common/sql/sql-bootstrapper/src/test/resources/test-schema.sql b/extensions/common/sql/sql-bootstrapper/src/test/resources/test-schema.sql new file mode 100644 index 00000000000..1b4cf1cb000 --- /dev/null +++ b/extensions/common/sql/sql-bootstrapper/src/test/resources/test-schema.sql @@ -0,0 +1,15 @@ +/* + * 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 + * + */ + +SELECT 1; \ No newline at end of file diff --git a/extensions/common/sql/sql-core/src/testFixtures/java/org/eclipse/edc/sql/testfixtures/PostgresqlEndToEndInstance.java b/extensions/common/sql/sql-core/src/testFixtures/java/org/eclipse/edc/sql/testfixtures/PostgresqlEndToEndInstance.java index 2294ad90a2a..88245633267 100644 --- a/extensions/common/sql/sql-core/src/testFixtures/java/org/eclipse/edc/sql/testfixtures/PostgresqlEndToEndInstance.java +++ b/extensions/common/sql/sql-core/src/testFixtures/java/org/eclipse/edc/sql/testfixtures/PostgresqlEndToEndInstance.java @@ -14,15 +14,10 @@ package org.eclipse.edc.sql.testfixtures; -import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.spi.persistence.EdcPersistenceException; -import java.io.IOException; -import java.nio.file.Files; -import java.sql.SQLException; import java.util.HashMap; import java.util.Map; -import java.util.stream.Stream; public interface PostgresqlEndToEndInstance { @@ -39,36 +34,6 @@ static void createDatabase(String participantName) { var postgres = new PostgresqlLocalInstance(USER, PASSWORD, JDBC_URL_PREFIX, participantName); postgres.createDatabase(); - - var extensionsFolder = TestUtils.findBuildRoot().toPath().resolve("extensions"); - var scripts = Stream.of( - "control-plane/store/sql/asset-index-sql", - "control-plane/store/sql/contract-definition-store-sql", - "control-plane/store/sql/contract-negotiation-store-sql", - "control-plane/store/sql/policy-definition-store-sql", - "control-plane/store/sql/transfer-process-store-sql", - "data-plane/store/sql/data-plane-store-sql", - "policy-monitor/store/sql/policy-monitor-store-sql", - "common/store/sql/edr-index-sql" - ) - .map(extensionsFolder::resolve) - .map(it -> it.resolve("docs")) - .map(it -> it.resolve("schema.sql")) - .toList(); - - try (var connection = postgres.getConnection(participantName)) { - for (var script : scripts) { - var sql = Files.readString(script); - - try (var statement = connection.createStatement()) { - statement.execute(sql); - } catch (Exception exception) { - throw new EdcPersistenceException(exception.getMessage(), exception); - } - } - } catch (SQLException | IOException e) { - throw new EdcPersistenceException(e); - } } static Map defaultDatasourceConfiguration(String name) { diff --git a/extensions/common/store/sql/edr-index-sql/build.gradle.kts b/extensions/common/store/sql/edr-index-sql/build.gradle.kts index 62ecdce7cc6..37ea97af1fe 100644 --- a/extensions/common/store/sql/edr-index-sql/build.gradle.kts +++ b/extensions/common/store/sql/edr-index-sql/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { api(project(":spi:common:transaction-spi")) implementation(project(":extensions:common:sql:sql-core")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) implementation(project(":spi:common:edr-store-spi")) implementation(project(":spi:common:transaction-datasource-spi")) testImplementation(project(":core:common:junit")) diff --git a/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java b/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java index 0c57b240146..bc80602a3b0 100644 --- a/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java +++ b/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java @@ -26,6 +26,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -54,6 +55,9 @@ public class SqlEndpointDataReferenceEntryIndexExtension implements ServiceExten @Inject private TypeManager typeManager; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Override public void initialize(ServiceExtensionContext context) { var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); @@ -62,6 +66,8 @@ public void initialize(ServiceExtensionContext context) { getStatementImpl(), queryExecutor); context.registerService(EndpointDataReferenceEntryIndex.class, sqlStore); + + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "edr-index-schema.sql"); } private EndpointDataReferenceEntryStatements getStatementImpl() { diff --git a/extensions/common/store/sql/edr-index-sql/docs/schema.sql b/extensions/common/store/sql/edr-index-sql/src/main/resources/edr-index-schema.sql similarity index 100% rename from extensions/common/store/sql/edr-index-sql/docs/schema.sql rename to extensions/common/store/sql/edr-index-sql/src/main/resources/edr-index-schema.sql diff --git a/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexTest.java b/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexTest.java index 86ea7882cf2..7e6e3383d79 100644 --- a/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexTest.java +++ b/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.edr.store.index.sql.schema.BaseSqlDialectStatements; import org.eclipse.edc.edr.store.index.sql.schema.postgres.PostgresDialectStatements; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; import org.junit.jupiter.api.AfterEach; @@ -28,8 +29,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; @ComponentTest @ExtendWith(PostgresqlStoreSetupExtension.class) @@ -44,7 +43,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) entryIndex = new SqlEndpointDataReferenceEntryIndex(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), new ObjectMapper(), statements, queryExecutor); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("edr-index-schema.sql"); extension.runQuery(schema); } diff --git a/extensions/control-plane/store/sql/asset-index-sql/README.md b/extensions/control-plane/store/sql/asset-index-sql/README.md index ea4e9bb4f75..23c6fdfa0de 100644 --- a/extensions/control-plane/store/sql/asset-index-sql/README.md +++ b/extensions/control-plane/store/sql/asset-index-sql/README.md @@ -4,7 +4,7 @@ Provides SQL persistence for assets. ## Prerequisites -Please apply this [schema](docs/schema.sql) to your SQL database. +Please apply this [schema](src/main/resources/asset-index-schema.sql) to your SQL database. ## Entity Diagram @@ -39,28 +39,36 @@ edc_asset ||--o{ edc_asset_property ## Configuration -| Key | Description | Mandatory | -|:---|:---|---| -| edc.datasource.asset.name | Datasource used by this extension | X | +| Key | Description | Mandatory | +|:--------------------------|:----------------------------------|-----------| +| edc.datasource.asset.name | Datasource used by this extension | X | ## Migrate from 0.3.1 to 0.3.2 This table structure has been changed, from 3 tables (one for the asset, one for properties and one for data address) to a single table with json fields. To migrate an existing database, please first add the 3 new columns in the `edc_asset` table: + ```sql -alter table edc_asset -add column properties json default '{}', -add column private_properties json default '{}', -add column data_address json default '{}'; +ALTER TABLE edc_asset + ADD COLUMN properties json DEFAULT '{}', + ADD COLUMN private_properties json DEFAULT '{}', + ADD COLUMN data_address json DEFAULT '{}'; ``` Then migrate the existing data in the new format: + ```sql -update edc_asset set -properties=(select json_object_agg(property_name, property_value) from edc_asset_property where asset_id_fk = edc_asset.asset_id and property_is_private = false), -private_properties=(select json_object_agg(property_name, property_value) from edc_asset_property where asset_id_fk = edc_asset.asset_id and property_is_private = true), -data_address=(select properties from edc_asset_dataaddress where asset_id_fk = edc_asset.asset_id); +UPDATE edc_asset +SET properties=(SELECT JSON_OBJECT_AGG(property_name, property_value) + FROM edc_asset_property + WHERE asset_id_fk = edc_asset.asset_id + AND property_is_private = FALSE), + private_properties=(SELECT JSON_OBJECT_AGG(property_name, property_value) + FROM edc_asset_property + WHERE asset_id_fk = edc_asset.asset_id + AND property_is_private = TRUE), + data_address=(SELECT properties FROM edc_asset_dataaddress WHERE asset_id_fk = edc_asset.asset_id); ``` After the migration, the tables `edc_asset_dataaddress` and `edc_asset_property` can be deleted. diff --git a/extensions/control-plane/store/sql/asset-index-sql/build.gradle.kts b/extensions/control-plane/store/sql/asset-index-sql/build.gradle.kts index 62c32f1ee7f..6fbf99ff276 100644 --- a/extensions/control-plane/store/sql/asset-index-sql/build.gradle.kts +++ b/extensions/control-plane/store/sql/asset-index-sql/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) implementation(project(":core:common:lib:util-lib")) testImplementation(project(":core:common:junit")) diff --git a/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java b/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java index d2252f06a6c..e5d9b88cec5 100644 --- a/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java +++ b/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java @@ -27,6 +27,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -55,6 +56,9 @@ public class SqlAssetIndexServiceExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Override public void initialize(ServiceExtensionContext context) { var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); @@ -63,6 +67,8 @@ public void initialize(ServiceExtensionContext context) { context.registerService(AssetIndex.class, sqlAssetLoader); context.registerService(DataAddressResolver.class, sqlAssetLoader); + + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "asset-index-schema.sql"); } private AssetStatements getDialect() { diff --git a/extensions/control-plane/store/sql/asset-index-sql/docs/schema.sql b/extensions/control-plane/store/sql/asset-index-sql/src/main/resources/asset-index-schema.sql similarity index 100% rename from extensions/control-plane/store/sql/asset-index-sql/docs/schema.sql rename to extensions/control-plane/store/sql/asset-index-sql/src/main/resources/asset-index-schema.sql diff --git a/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/PostgresAssetIndexTest.java b/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/PostgresAssetIndexTest.java index 365df80fe6b..207b66f786a 100644 --- a/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/PostgresAssetIndexTest.java +++ b/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/PostgresAssetIndexTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.controlplane.store.sql.assetindex.schema.postgres.PostgresDialectStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -29,8 +30,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; @ComponentTest @ExtendWith(PostgresqlStoreSetupExtension.class) @@ -48,7 +47,7 @@ void setUp(PostgresqlStoreSetupExtension setupExtension, QueryExecutor queryExec sqlAssetIndex = new SqlAssetIndex(setupExtension.getDataSourceRegistry(), setupExtension.getDatasourceName(), setupExtension.getTransactionContext(), new ObjectMapper(), sqlStatements, queryExecutor); - var schema = Files.readString(Paths.get("docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("asset-index-schema.sql"); setupExtension.runQuery(schema); } diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/README.md b/extensions/control-plane/store/sql/contract-definition-store-sql/README.md index 28e33920364..f2d12342d34 100644 --- a/extensions/control-plane/store/sql/contract-definition-store-sql/README.md +++ b/extensions/control-plane/store/sql/contract-definition-store-sql/README.md @@ -4,7 +4,7 @@ Provides SQL persistence for contract definitions. ## Prerequisites -Please apply this [schema](docs/schema.sql) to your SQL database. +Please apply this [schema](src/main/resources/contract-definition-schema.sql) to your SQL database. ## Entity Diagram diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/build.gradle.kts b/extensions/control-plane/store/sql/contract-definition-store-sql/build.gradle.kts index b36ff972c36..d467c8da676 100644 --- a/extensions/control-plane/store/sql/contract-definition-store-sql/build.gradle.kts +++ b/extensions/control-plane/store/sql/contract-definition-store-sql/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { api(project(":spi:common:transaction-spi")) implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) testImplementation(project(":spi:common:policy-model")) diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java b/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java index cf64d05f6ca..37c6bcfc643 100644 --- a/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java +++ b/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java @@ -27,6 +27,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -55,6 +56,9 @@ public class SqlContractDefinitionStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Override public void initialize(ServiceExtensionContext context) { var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); @@ -63,6 +67,8 @@ public void initialize(ServiceExtensionContext context) { getStatementImpl(), typeManager.getMapper(), queryExecutor); context.registerService(ContractDefinitionStore.class, sqlContractDefinitionStore); + + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "contract-definition-schema.sql"); } private ContractDefinitionStatements getStatementImpl() { diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/docs/schema.sql b/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/resources/contract-definition-schema.sql similarity index 100% rename from extensions/control-plane/store/sql/contract-definition-store-sql/docs/schema.sql rename to extensions/control-plane/store/sql/contract-definition-store-sql/src/main/resources/contract-definition-schema.sql diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/PostgresContractDefinitionStoreTest.java b/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/PostgresContractDefinitionStoreTest.java index b0ebd3c67ad..8ca4470b462 100644 --- a/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/PostgresContractDefinitionStoreTest.java +++ b/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/PostgresContractDefinitionStoreTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.controlplane.store.sql.contractdefinition.schema.postgres.PostgresDialectStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -29,8 +30,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; @ComponentTest @ExtendWith(PostgresqlStoreSetupExtension.class) @@ -48,7 +47,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) sqlContractDefinitionStore = new SqlContractDefinitionStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), queryExecutor); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("contract-definition-schema.sql"); extension.runQuery(schema); } diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/README.md b/extensions/control-plane/store/sql/contract-negotiation-store-sql/README.md index 4c437ca4740..435421d43d2 100644 --- a/extensions/control-plane/store/sql/contract-negotiation-store-sql/README.md +++ b/extensions/control-plane/store/sql/contract-negotiation-store-sql/README.md @@ -5,7 +5,7 @@ work but might have unexpected side effects!_** ## 1. Table schema -see [schema.sql](docs/schema.sql). +see [schema.sql](src/main/resources/contract-negotiation-schema.sql). As an alternative to storing `ContractAgreement`s in a dedicated table, it could also be serialized and stored as column in the `contract_negotiation` table. However, we will need to be able to list all contract agreements at some point, so diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/build.gradle.kts b/extensions/control-plane/store/sql/contract-negotiation-store-sql/build.gradle.kts index e2ab555503e..f940ceb420c 100644 --- a/extensions/control-plane/store/sql/contract-negotiation-store-sql/build.gradle.kts +++ b/extensions/control-plane/store/sql/contract-negotiation-store-sql/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) implementation(project(":extensions:common:sql:sql-lease")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java index 0a06873d9d2..8671a46fc11 100644 --- a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java +++ b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java @@ -25,6 +25,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -54,11 +55,17 @@ public class SqlContractNegotiationStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Override public void initialize(ServiceExtensionContext context) { - var sqlStore = new SqlContractNegotiationStore(dataSourceRegistry, getDataSourceName(context), trxContext, + var dataSourceName = getDataSourceName(context); + var sqlStore = new SqlContractNegotiationStore(dataSourceRegistry, dataSourceName, trxContext, typeManager.getMapper(), getStatementImpl(), context.getRuntimeId(), clock, queryExecutor); context.registerService(ContractNegotiationStore.class, sqlStore); + + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "contract-negotiation-schema.sql"); } /** diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/docs/schema.sql b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/resources/contract-negotiation-schema.sql similarity index 100% rename from extensions/control-plane/store/sql/contract-negotiation-store-sql/docs/schema.sql rename to extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/resources/contract-negotiation-schema.sql diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/store/PostgresContractNegotiationStoreTest.java b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/store/PostgresContractNegotiationStoreTest.java index ccddf4c0c31..06aceef3967 100644 --- a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/store/PostgresContractNegotiationStoreTest.java +++ b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/store/PostgresContractNegotiationStoreTest.java @@ -18,6 +18,7 @@ import org.eclipse.edc.connector.controlplane.store.sql.contractnegotiation.store.schema.postgres.PostgresDialectStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.lease.testfixtures.LeaseUtil; @@ -27,8 +28,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.time.Duration; /** @@ -51,7 +50,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) store = new SqlContractNegotiationStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), manager.getMapper(), statements, CONNECTOR_NAME, clock, queryExecutor); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("contract-negotiation-schema.sql"); extension.runQuery(schema); leaseUtil = new LeaseUtil(extension.getTransactionContext(), extension::getConnection, statements, clock); } diff --git a/extensions/control-plane/store/sql/control-plane-sql/build.gradle.kts b/extensions/control-plane/store/sql/control-plane-sql/build.gradle.kts index cc26466c722..7b59a818936 100644 --- a/extensions/control-plane/store/sql/control-plane-sql/build.gradle.kts +++ b/extensions/control-plane/store/sql/control-plane-sql/build.gradle.kts @@ -18,13 +18,13 @@ plugins { } dependencies { - implementation(project(":extensions:common:sql:sql-core")) - implementation(project(":extensions:common:sql:sql-lease")) - implementation(project(":extensions:control-plane:store:sql:asset-index-sql")) - implementation(project(":extensions:control-plane:store:sql:contract-definition-store-sql")) - implementation(project(":extensions:control-plane:store:sql:contract-negotiation-store-sql")) - implementation(project(":extensions:control-plane:store:sql:policy-definition-store-sql")) - implementation(project(":extensions:control-plane:store:sql:transfer-process-store-sql")) + runtimeOnly(project(":extensions:common:sql:sql-core")) + runtimeOnly(project(":extensions:common:sql:sql-lease")) + runtimeOnly(project(":extensions:control-plane:store:sql:asset-index-sql")) + runtimeOnly(project(":extensions:control-plane:store:sql:contract-definition-store-sql")) + runtimeOnly(project(":extensions:control-plane:store:sql:contract-negotiation-store-sql")) + runtimeOnly(project(":extensions:control-plane:store:sql:policy-definition-store-sql")) + runtimeOnly(project(":extensions:control-plane:store:sql:transfer-process-store-sql")) testImplementation(project(":core:common:junit")) testImplementation(project(":core:control-plane:control-plane-catalog")) diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/README.md b/extensions/control-plane/store/sql/policy-definition-store-sql/README.md index c2e94cf4621..a5ac9007a29 100644 --- a/extensions/control-plane/store/sql/policy-definition-store-sql/README.md +++ b/extensions/control-plane/store/sql/policy-definition-store-sql/README.md @@ -7,7 +7,7 @@ but might have unexpected side effects! ## Prerequisites -Please apply this [schema](docs/schema.sql) to your SQL database. +Please apply this [schema](src/main/resources/policy-definition-schema.sql) to your SQL database. ## Entity Diagram @@ -37,6 +37,6 @@ entity edc_policydefinitions { ## Configuration -| Key | Description | Mandatory | -|:---------------------------|:---|---| -| edc.datasource.policy.name | Datasource used by this extension | X | +| Key | Description | Mandatory | +|:---------------------------|:----------------------------------|-----------| +| edc.datasource.policy.name | Datasource used by this extension | X | diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/build.gradle.kts b/extensions/control-plane/store/sql/policy-definition-store-sql/build.gradle.kts index fce329a2080..2fb33da6292 100644 --- a/extensions/control-plane/store/sql/policy-definition-store-sql/build.gradle.kts +++ b/extensions/control-plane/store/sql/policy-definition-store-sql/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { api(project(":spi:common:transaction-spi")) implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java b/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java index 14d4118f13a..821c19f7def 100644 --- a/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java +++ b/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java @@ -26,6 +26,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -50,13 +51,18 @@ public class SqlPolicyStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; @Override public void initialize(ServiceExtensionContext context) { - var sqlPolicyStore = new SqlPolicyDefinitionStore(dataSourceRegistry, getDataSourceName(context), transactionContext, + var dataSourceName = getDataSourceName(context); + var sqlPolicyStore = new SqlPolicyDefinitionStore(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), getStatementImpl(), queryExecutor); context.registerService(PolicyDefinitionStore.class, sqlPolicyStore); + + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "policy-definition-schema.sql"); } /** diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/docs/schema.sql b/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/resources/policy-definition-schema.sql similarity index 100% rename from extensions/control-plane/store/sql/policy-definition-store-sql/docs/schema.sql rename to extensions/control-plane/store/sql/policy-definition-store-sql/src/main/resources/policy-definition-schema.sql diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/PostgresPolicyDefinitionStoreTest.java b/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/PostgresPolicyDefinitionStoreTest.java index 638b2cdecbe..37d2710ea0c 100644 --- a/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/PostgresPolicyDefinitionStoreTest.java +++ b/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/PostgresPolicyDefinitionStoreTest.java @@ -19,6 +19,7 @@ import org.eclipse.edc.connector.controlplane.store.sql.policydefinition.store.schema.postgres.PostgresDialectStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -27,8 +28,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; /** * This test aims to verify those parts of the policy definition store, that are specific to Postgres, e.g. JSON query @@ -49,7 +48,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) sqlPolicyStore = new SqlPolicyDefinitionStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), typeManager.getMapper(), statements, queryExecutor); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("policy-definition-schema.sql"); extension.runQuery(schema); } diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/README.md b/extensions/control-plane/store/sql/transfer-process-store-sql/README.md index 050700bfdac..c9adabde237 100644 --- a/extensions/control-plane/store/sql/transfer-process-store-sql/README.md +++ b/extensions/control-plane/store/sql/transfer-process-store-sql/README.md @@ -5,7 +5,7 @@ work but might have unexpected side effects!_** ## Table schema DDL -please refer to [schema.sql](docs/schema.sql): +please refer to [schema.sql](src/main/resources/transfer-process-schema.sql): ## Translating the `TransferProcessStore` interface into SQL statements @@ -26,8 +26,9 @@ encoded in those clauses, offering a fluent Java API. ## Migrate from 0.5.1 to 0.6.0 -The schema has changed, the columns contained in `edc_data_request` have been moved to `edc_transfer_process` with this +The schema has changed, the columns contained in `edc_data_request` have been moved to `edc_transfer_process` with this mapping: + - `datarequest_id` -> `correlation_id` - `connector_address` -> `counter_party_address` - `protocol` -> `protocol` @@ -36,6 +37,7 @@ mapping: - `data_destination` -> `data_destination` These columns need to be added to `edc_transfer_process`: + ```sql correlation_id VARCHAR, counter_party_address VARCHAR, diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/build.gradle.kts b/extensions/control-plane/store/sql/transfer-process-store-sql/build.gradle.kts index eada29d339b..58ac60f0355 100644 --- a/extensions/control-plane/store/sql/transfer-process-store-sql/build.gradle.kts +++ b/extensions/control-plane/store/sql/transfer-process-store-sql/build.gradle.kts @@ -25,6 +25,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) implementation(project(":extensions:common:sql:sql-lease")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) testImplementation(libs.assertj) diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java b/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java index 7bb146962fb..1b4542080c5 100644 --- a/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java +++ b/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java @@ -26,6 +26,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -54,11 +55,17 @@ public class SqlTransferProcessStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Override public void initialize(ServiceExtensionContext context) { - var store = new SqlTransferProcessStore(dataSourceRegistry, getDataSourceName(context), trxContext, + var dataSourceName = getDataSourceName(context); + var store = new SqlTransferProcessStore(dataSourceRegistry, dataSourceName, trxContext, typeManager.getMapper(), getStatementImpl(), context.getRuntimeId(), clock, queryExecutor); context.registerService(TransferProcessStore.class, store); + + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "transfer-process-schema.sql"); } /** diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/docs/schema.sql b/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/resources/transfer-process-schema.sql similarity index 100% rename from extensions/control-plane/store/sql/transfer-process-store-sql/docs/schema.sql rename to extensions/control-plane/store/sql/transfer-process-store-sql/src/main/resources/transfer-process-schema.sql diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/PostgresTransferProcessStoreTest.java b/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/PostgresTransferProcessStoreTest.java index 84dab374969..05d7ef58e86 100644 --- a/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/PostgresTransferProcessStoreTest.java +++ b/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/PostgresTransferProcessStoreTest.java @@ -20,6 +20,7 @@ import org.eclipse.edc.connector.controlplane.transfer.spi.testfixtures.store.TransferProcessStoreTestBase; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.lease.testfixtures.LeaseUtil; @@ -29,8 +30,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.time.Duration; @ComponentTest @@ -52,7 +51,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) extension.getTransactionContext(), typeManager.getMapper(), statements, "test-connector", clock, queryExecutor); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("transfer-process-schema.sql"); extension.runQuery(schema); } diff --git a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/build.gradle.kts b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/build.gradle.kts index a84d4071177..6c12010dd8d 100644 --- a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/build.gradle.kts +++ b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/build.gradle.kts @@ -11,6 +11,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) implementation(project(":extensions:common:sql:sql-lease")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) testImplementation(testFixtures(project(":spi:data-plane-selector:data-plane-selector-spi"))) diff --git a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java index 243863e901d..a47b069b5ff 100644 --- a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java +++ b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java @@ -26,6 +26,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -59,6 +60,9 @@ public class SqlDataPlaneInstanceStoreExtension implements ServiceExtension { @Inject private Clock clock; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Override public String name() { return NAME; @@ -66,7 +70,9 @@ public String name() { @Provider public DataPlaneInstanceStore dataPlaneInstanceStore(ServiceExtensionContext context) { - return new SqlDataPlaneInstanceStore(dataSourceRegistry, getDataSourceName(context), transactionContext, + var dataSourceName = getDataSourceName(context); + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "dataplane-instance-schema.sql"); + return new SqlDataPlaneInstanceStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), queryExecutor, clock, context.getRuntimeId()); } diff --git a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/docs/schema.sql b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/resources/dataplane-instance-schema.sql similarity index 100% rename from extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/docs/schema.sql rename to extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/resources/dataplane-instance-schema.sql diff --git a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/PostgresDataPlaneInstanceStoreTest.java b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/PostgresDataPlaneInstanceStoreTest.java index a95edfe93fb..c52d85ebe2e 100644 --- a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/PostgresDataPlaneInstanceStoreTest.java +++ b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/PostgresDataPlaneInstanceStoreTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.dataplane.selector.store.sql.schema.postgres.PostgresDataPlaneInstanceStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.lease.testfixtures.LeaseUtil; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -29,8 +30,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.time.Clock; import java.time.Duration; @@ -53,7 +52,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) leaseUtil = new LeaseUtil(extension.getTransactionContext(), extension::getConnection, statements, clock); store = new SqlDataPlaneInstanceStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), queryExecutor, clock, CONNECTOR_NAME); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("dataplane-instance-schema.sql"); extension.runQuery(schema); } diff --git a/extensions/data-plane/store/sql/accesstokendata-store-sql/build.gradle.kts b/extensions/data-plane/store/sql/accesstokendata-store-sql/build.gradle.kts index 576fa0302fe..b758e2ca9ae 100644 --- a/extensions/data-plane/store/sql/accesstokendata-store-sql/build.gradle.kts +++ b/extensions/data-plane/store/sql/accesstokendata-store-sql/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) testImplementation(testFixtures(project(":spi:data-plane:data-plane-spi"))) diff --git a/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java index 873879efd8c..4577e286cf7 100644 --- a/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java +++ b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java @@ -26,6 +26,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -59,6 +60,8 @@ public class SqlAccessTokenDataStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; @Override public String name() { @@ -67,7 +70,9 @@ public String name() { @Provider public AccessTokenDataStore dataPlaneStore(ServiceExtensionContext context) { - return new SqlAccessTokenDataStore(dataSourceRegistry, getDataSourceName(context), transactionContext, + var dataSourceName = getDataSourceName(context); + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "accesstoken-data-schema.sql"); + return new SqlAccessTokenDataStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), queryExecutor); } diff --git a/extensions/data-plane/store/sql/accesstokendata-store-sql/docs/schema.sql b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/resources/accesstoken-data-schema.sql similarity index 100% rename from extensions/data-plane/store/sql/accesstokendata-store-sql/docs/schema.sql rename to extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/resources/accesstoken-data-schema.sql diff --git a/extensions/data-plane/store/sql/accesstokendata-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreTest.java b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreTest.java index f4da9cecd1a..8f4a17c3855 100644 --- a/extensions/data-plane/store/sql/accesstokendata-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreTest.java +++ b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.dataplane.store.sql.schema.postgres.PostgresAccessTokenDataStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -29,8 +30,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; @ComponentTest @ExtendWith(PostgresqlStoreSetupExtension.class) @@ -47,7 +46,7 @@ void setup(PostgresqlStoreSetupExtension setupExtension, QueryExecutor queryExec sqlStore = new SqlAccessTokenDataStore(setupExtension.getDataSourceRegistry(), setupExtension.getDatasourceName(), setupExtension.getTransactionContext(), sqlStatements, new ObjectMapper(), queryExecutor); - var schema = Files.readString(Paths.get("docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("accesstoken-data-schema.sql"); setupExtension.runQuery(schema); } diff --git a/extensions/data-plane/store/sql/data-plane-store-sql/README.md b/extensions/data-plane/store/sql/data-plane-store-sql/README.md index 3dc434fe26f..5f44ca01b9d 100644 --- a/extensions/data-plane/store/sql/data-plane-store-sql/README.md +++ b/extensions/data-plane/store/sql/data-plane-store-sql/README.md @@ -4,7 +4,7 @@ Provides SQL persistence for data flow transfer state. ## Prerequisites -Please apply this [schema](docs/schema.sql) to your SQL database. +Please apply this [schema](src/main/resources/dataplane-schema.sql) to your SQL database. ## Entity Diagram diff --git a/extensions/data-plane/store/sql/data-plane-store-sql/build.gradle.kts b/extensions/data-plane/store/sql/data-plane-store-sql/build.gradle.kts index 1c048e1bc2a..e2cf4277dc6 100644 --- a/extensions/data-plane/store/sql/data-plane-store-sql/build.gradle.kts +++ b/extensions/data-plane/store/sql/data-plane-store-sql/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) implementation(project(":extensions:common:sql:sql-lease")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) testImplementation(testFixtures(project(":spi:data-plane:data-plane-spi"))) diff --git a/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java b/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java index f75ff74a0c0..b9a7378766b 100644 --- a/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java +++ b/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java @@ -25,6 +25,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -58,6 +59,8 @@ public class SqlDataPlaneStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; @Override public String name() { @@ -66,7 +69,9 @@ public String name() { @Provider public DataPlaneStore dataPlaneStore(ServiceExtensionContext context) { - return new SqlDataPlaneStore(dataSourceRegistry, getDataSourceName(context), transactionContext, + var dataSourceName = getDataSourceName(context); + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "dataplane-schema.sql"); + return new SqlDataPlaneStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), clock, queryExecutor, context.getRuntimeId()); } diff --git a/extensions/data-plane/store/sql/data-plane-store-sql/docs/schema.sql b/extensions/data-plane/store/sql/data-plane-store-sql/src/main/resources/dataplane-schema.sql similarity index 100% rename from extensions/data-plane/store/sql/data-plane-store-sql/docs/schema.sql rename to extensions/data-plane/store/sql/data-plane-store-sql/src/main/resources/dataplane-schema.sql diff --git a/extensions/data-plane/store/sql/data-plane-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/PostgresDataPlaneStoreTest.java b/extensions/data-plane/store/sql/data-plane-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/PostgresDataPlaneStoreTest.java index 93751f37d30..1ccf0560efb 100644 --- a/extensions/data-plane/store/sql/data-plane-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/PostgresDataPlaneStoreTest.java +++ b/extensions/data-plane/store/sql/data-plane-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/store/sql/PostgresDataPlaneStoreTest.java @@ -20,6 +20,7 @@ import org.eclipse.edc.connector.dataplane.store.sql.schema.postgres.PostgresDataPlaneStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.lease.testfixtures.LeaseUtil; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -28,8 +29,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.time.Clock; import java.time.Duration; @@ -52,7 +51,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) leaseUtil = new LeaseUtil(extension.getTransactionContext(), extension::getConnection, statements, clock); store = new SqlDataPlaneStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), clock, queryExecutor, "test-connector"); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("dataplane-schema.sql"); extension.runQuery(schema); } diff --git a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/build.gradle.kts b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/build.gradle.kts index fb4aa827ca8..dc7d2b9c91a 100644 --- a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/build.gradle.kts +++ b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(project(":spi:common:transaction-datasource-spi")) implementation(project(":extensions:common:sql:sql-core")) implementation(project(":extensions:common:sql:sql-lease")) + implementation(project(":extensions:common:sql:sql-bootstrapper")) testImplementation(project(":core:common:junit")) testImplementation(testFixtures(project(":spi:policy-monitor:policy-monitor-spi"))) diff --git a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java index cfb6be4a4f9..fff770ea7f1 100644 --- a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java +++ b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java @@ -24,6 +24,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -54,11 +55,17 @@ public class SqlPolicyMonitorStoreExtension implements ServiceExtension { @Inject private QueryExecutor queryExecutor; + @Inject + private SqlSchemaBootstrapper sqlSchemaBootstrapper; + @Provider public PolicyMonitorStore policyMonitorStore(ServiceExtensionContext context) { var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DEFAULT_DATASOURCE); + sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "policy-monitor-schema.sql"); + return new SqlPolicyMonitorStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), clock, queryExecutor, context.getRuntimeId()); + } /** diff --git a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/docs/schema.sql b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/resources/policy-monitor-schema.sql similarity index 100% rename from extensions/policy-monitor/store/sql/policy-monitor-store-sql/docs/schema.sql rename to extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/resources/policy-monitor-schema.sql diff --git a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/test/java/org/eclipse/edc/connector/policy/monitor/store/sql/PostgresPolicyMonitorStoreTest.java b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/test/java/org/eclipse/edc/connector/policy/monitor/store/sql/PostgresPolicyMonitorStoreTest.java index bd804eb4ad4..c45e30b8ed8 100644 --- a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/test/java/org/eclipse/edc/connector/policy/monitor/store/sql/PostgresPolicyMonitorStoreTest.java +++ b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/test/java/org/eclipse/edc/connector/policy/monitor/store/sql/PostgresPolicyMonitorStoreTest.java @@ -20,6 +20,7 @@ import org.eclipse.edc.connector.policy.monitor.store.sql.schema.PostgresPolicyMonitorStatements; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.lease.testfixtures.LeaseUtil; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -28,8 +29,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.time.Clock; import java.time.Duration; @@ -52,7 +51,7 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) leaseUtil = new LeaseUtil(extension.getTransactionContext(), extension::getConnection, statements, clock); store = new SqlPolicyMonitorStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), clock, queryExecutor, "test-connector"); - var schema = Files.readString(Paths.get("./docs/schema.sql")); + var schema = TestUtils.getResourceFileContentAsString("policy-monitor-schema.sql"); extension.runQuery(schema); } diff --git a/settings.gradle.kts b/settings.gradle.kts index bdc1a65e00a..1786b12907e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -146,6 +146,7 @@ include(":extensions:common:metrics:micrometer-core") include(":extensions:common:monitor:monitor-jdk-logger") include(":extensions:common:sql:sql-core") include(":extensions:common:sql:sql-lease") +include(":extensions:common:sql:sql-bootstrapper") include(":extensions:common:sql:sql-pool:sql-pool-apache-commons") include(":extensions:common:transaction") include(":extensions:common:transaction:transaction-atomikos") 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 58ff179f607..ac6a359552a 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 @@ -135,6 +135,7 @@ public Map controlPlaneConfiguration() { public Map controlPlanePostgresConfiguration() { var baseConfiguration = controlPlaneConfiguration(); baseConfiguration.putAll(defaultDatasourceConfiguration(getName())); + baseConfiguration.put("edc.sql.schema.autocreate", "true"); return baseConfiguration; } @@ -169,6 +170,7 @@ public Map controlPlaneEmbeddedDataPlaneConfiguration() { public Map dataPlanePostgresConfiguration() { var baseConfiguration = dataPlaneConfiguration(); baseConfiguration.putAll(defaultDatasourceConfiguration(getName())); + baseConfiguration.put("edc.sql.schema.autocreate", "true"); return baseConfiguration; } @@ -200,8 +202,8 @@ public DataAddress getEdr(String transferProcessId) { /** * Pull data from provider using EDR. * - * @param edr endpoint data reference - * @param queryParams query parameters + * @param edr endpoint data reference + * @param queryParams query parameters * @param bodyAssertion assertion to be verified on the body */ public void pullData(DataAddress edr, Map queryParams, ThrowingConsumer bodyAssertion) { 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 dcfce9270bf..bc5f9ea166f 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 @@ -37,6 +37,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.RegisterExtension; @@ -93,6 +94,15 @@ static void afterAll() { stopQuietly(providerDataSource); } + private static @NotNull Map httpSourceDataAddress() { + return Map.of( + EDC_NAMESPACE + "name", "transfer-test", + EDC_NAMESPACE + "baseUrl", "http://localhost:" + providerDataSource.getPort() + "/source", + EDC_NAMESPACE + "type", "HttpData", + EDC_NAMESPACE + "proxyQueryParams", "true" + ); + } + @Test void httpPull_dataTransfer_withCallbacks() { providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); @@ -266,15 +276,6 @@ public JsonObject createCallback(String url, boolean transactional, Set .build(); } - private static @NotNull Map httpSourceDataAddress() { - return Map.of( - EDC_NAMESPACE + "name", "transfer-test", - EDC_NAMESPACE + "baseUrl", "http://localhost:" + providerDataSource.getPort() + "/source", - EDC_NAMESPACE + "type", "HttpData", - EDC_NAMESPACE + "proxyQueryParams", "true" - ); - } - private HttpResponse cacheEdr(HttpRequest request, Map events) { try { @@ -334,15 +335,15 @@ class InMemory extends Tests { @RegisterExtension static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); + Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); @Override protected Vault getDataplaneVault() { @@ -360,7 +361,7 @@ class EmbeddedDataPlane extends Tests { @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("provider-control-plane", PROVIDER.controlPlaneEmbeddedDataPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("provider-control-plane", PROVIDER.controlPlaneEmbeddedDataPlaneConfiguration())); @Override protected Vault getDataplaneVault() { @@ -372,6 +373,7 @@ protected Vault getDataplaneVault() { @PostgresqlIntegrationTest class Postgres extends Tests { + @Order(0) // must be the first extension to be evaluated since it creates the database @RegisterExtension static final BeforeAllCallback CREATE_DATABASES = context -> { createDatabase(CONSUMER.getName()); @@ -380,15 +382,15 @@ class Postgres extends Tests { @RegisterExtension static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.POSTGRES_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration())); + Runtimes.POSTGRES_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.POSTGRES_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration())); + Runtimes.POSTGRES_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( - Runtimes.POSTGRES_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration())); + Runtimes.POSTGRES_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration())); @Override protected Vault getDataplaneVault() { 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 83ea8d958f4..4ee160a7223 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 @@ -23,6 +23,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.RegisterExtension; @@ -131,15 +132,15 @@ class InMemory extends Tests { @RegisterExtension static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); + Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); @Override protected Vault getDataplaneVault() { @@ -153,11 +154,11 @@ class EmbeddedDataPlane extends Tests { @RegisterExtension static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("provider-control-plane", PROVIDER.controlPlaneEmbeddedDataPlaneConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("provider-control-plane", PROVIDER.controlPlaneEmbeddedDataPlaneConfiguration())); @Override protected Vault getDataplaneVault() { @@ -169,6 +170,7 @@ protected Vault getDataplaneVault() { @PostgresqlIntegrationTest class Postgres extends Tests { + @Order(0) // must be the first extension to be evaluated since it creates the database @RegisterExtension static final BeforeAllCallback CREATE_DATABASES = context -> { createDatabase(CONSUMER.getName()); @@ -177,15 +179,15 @@ class Postgres extends Tests { @RegisterExtension static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.POSTGRES_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration())); + Runtimes.POSTGRES_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.POSTGRES_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration())); + Runtimes.POSTGRES_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( - Runtimes.POSTGRES_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration())); + Runtimes.POSTGRES_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration())); @Override protected Vault getDataplaneVault() { diff --git a/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/ManagementEndToEndExtension.java b/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/ManagementEndToEndExtension.java index c689aef89c1..10c7789aa19 100644 --- a/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/ManagementEndToEndExtension.java +++ b/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/ManagementEndToEndExtension.java @@ -55,6 +55,10 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte static class InMemory extends ManagementEndToEndExtension { + protected InMemory() { + super(context()); + } + private static ManagementEndToEndTestContext context() { var managementPort = getFreePort(); var protocolPort = getFreePort(); @@ -79,14 +83,14 @@ private static ManagementEndToEndTestContext context() { return new ManagementEndToEndTestContext(runtime, managementPort, protocolPort); } - protected InMemory() { - super(context()); - } - } static class Postgres extends ManagementEndToEndExtension { + protected Postgres() { + super(context()); + } + private static ManagementEndToEndTestContext context() { var managementPort = getFreePort(); var protocolPort = getFreePort(); @@ -106,10 +110,14 @@ private static ManagementEndToEndTestContext context() { put("edc.datasource.default.url", PostgresqlEndToEndInstance.JDBC_URL_PREFIX + "runtime"); put("edc.datasource.default.user", PostgresqlEndToEndInstance.USER); put("edc.datasource.default.password", PostgresqlEndToEndInstance.PASSWORD); + put("edc.sql.schema.autocreate", "true"); } }, ":system-tests:management-api:management-api-test-runtime", ":extensions:control-plane:store:sql:control-plane-sql", + ":extensions:policy-monitor:store:sql:policy-monitor-store-sql", + ":extensions:common:store:sql:edr-index-sql", + ":extensions:data-plane:store:sql:data-plane-store-sql", ":extensions:common:sql:sql-pool:sql-pool-apache-commons", ":extensions:common:transaction:transaction-local" ); @@ -117,10 +125,6 @@ private static ManagementEndToEndTestContext context() { return new ManagementEndToEndTestContext(runtime, managementPort, protocolPort); } - protected Postgres() { - super(context()); - } - @Override public void beforeAll(ExtensionContext extensionContext) { createDatabase("runtime");