Skip to content

Commit

Permalink
Merge pull request #1024 from Think-iT-Labs/1003-fix-asset-properties…
Browse files Browse the repository at this point in the history
…-transformation

fix: migrate asset json properties from array to map
  • Loading branch information
ndr-brt authored Feb 5, 2024
2 parents cbe5a6b + f434c6a commit 7b0ad5b
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 67 deletions.
4 changes: 3 additions & 1 deletion edc-extensions/postgresql-migration/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ dependencies {
implementation(libs.edc.sql.core)
runtimeOnly(libs.postgres)

implementation("org.flywaydb:flyway-core:9.22.3")
implementation(libs.flyway.core)

testImplementation(testFixtures(libs.edc.sql.core))
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,15 @@
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.sql.DriverManagerConnectionFactory;
import org.eclipse.edc.sql.datasource.ConnectionFactoryDataSource;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.MigrationVersion;

import java.util.Objects;
import java.util.Properties;

import static org.flywaydb.core.api.MigrationVersion.LATEST;

abstract class AbstractPostgresqlMigrationExtension implements ServiceExtension {

private static final String EDC_DATASOURCE_PREFIX = "edc.datasource";
private static final String MIGRATION_LOCATION_BASE =
String.format("classpath:%s", AbstractPostgresqlMigrationExtension.class.getPackageName().replace(".", "/"));

private static final String DEFAULT_MIGRATION_ENABLED_TEMPLATE = "true";
@Setting(value = "Enable/disables subsystem schema migration", defaultValue = DEFAULT_MIGRATION_ENABLED_TEMPLATE, type = "boolean")
Expand Down Expand Up @@ -79,19 +77,8 @@ public void initialize(final ServiceExtensionContext context) {
var driverManagerConnectionFactory = new DriverManagerConnectionFactory();
var dataSource = new ConnectionFactoryDataSource(driverManagerConnectionFactory, jdbcUrl, jdbcProperties);

var flyway =
Flyway.configure()
.baselineVersion(MigrationVersion.fromVersion("0.0.0"))
.failOnMissingLocations(true)
.dataSource(dataSource)
.table("flyway_schema_history_%s".formatted(subSystemName))
.locations("%s/%s".formatted(MIGRATION_LOCATION_BASE, subSystemName))
.defaultSchema(config.getString(MIGRATION_SCHEMA, DEFAULT_MIGRATION_SCHEMA))
.load();

flyway.baseline();

var migrateResult = flyway.migrate();
var defaultSchema = config.getString(MIGRATION_SCHEMA, DEFAULT_MIGRATION_SCHEMA);
var migrateResult = FlywayManager.migrate(dataSource, subSystemName, defaultSchema, LATEST);

if (!migrateResult.success) {
throw new EdcPersistenceException(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.tractusx.edc.postgresql.migration;

import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.api.output.MigrateResult;

import javax.sql.DataSource;


public class FlywayManager {

private static final String MIGRATION_LOCATION_BASE =
String.format("classpath:%s", FlywayManager.class.getPackageName().replace(".", "/"));

public static MigrateResult migrate(DataSource dataSource, String subSystemName, String defaultSchema, MigrationVersion target) {
var flyway =
Flyway.configure()
.baselineVersion(MigrationVersion.fromVersion("0.0.0"))
.failOnMissingLocations(true)
.dataSource(dataSource)
.table("flyway_schema_history_%s".formatted(subSystemName))
.locations("%s/%s".formatted(MIGRATION_LOCATION_BASE, subSystemName))
.defaultSchema(defaultSchema)
.target(target)
.load();

flyway.baseline();

return flyway.migrate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--
-- Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft
--
-- 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 - Migration into one table
--

UPDATE edc_asset SET
properties = (select json_object_agg(json_array_elements->>'property_name', json_array_elements->>'property_value') from json_array_elements(properties) as json_array_elements),
private_properties = (select json_object_agg(json_array_elements->>'property_name', json_array_elements->>'property_value') from json_array_elements(private_properties) as json_array_elements)
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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.tractusx.edc.postgresql.migration;

import org.eclipse.edc.connector.store.sql.assetindex.SqlAssetIndex;
import org.eclipse.edc.connector.store.sql.assetindex.schema.postgres.PostgresDialectStatements;
import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.spi.types.domain.asset.Asset;
import org.eclipse.edc.sql.QueryExecutor;
import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension;
import org.flywaydb.core.api.MigrationVersion;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

@PostgresqlDbIntegrationTest
@ExtendWith(PostgresqlStoreSetupExtension.class)
class AssetPostgresqlMigrationExtensionTest {

private SqlAssetIndex store;

@BeforeEach
void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) {
store = new SqlAssetIndex(extension.getDataSourceRegistry(), extension.getDatasourceName(),
extension.getTransactionContext(), new TypeManager().getMapper(), new PostgresDialectStatements(),
queryExecutor);
}

@Test // bugfix https://github.com/eclipse-tractusx/tractusx-edc/issues/1003
void version006shouldTransformPropertiesListToMap(PostgresqlStoreSetupExtension extension) {
var dataSource = extension.getDataSourceRegistry().resolve(extension.getDatasourceName());
FlywayManager.migrate(dataSource, "asset", "public", MigrationVersion.fromVersion("0.0.5"));

insertAsset(extension, "1");
insertAsset(extension, "2");

FlywayManager.migrate(dataSource, "asset", "public", MigrationVersion.fromVersion("0.0.6"));

var result = store.findById("1");

assertThat(result).isNotNull();
assertThat(result.getProperties()).containsExactlyInAnyOrderEntriesOf(
Map.of(Asset.PROPERTY_ID, "1", "key", "value1", "anotherKey", "anotherValue1"));
assertThat(result.getPrivateProperties()).containsExactlyInAnyOrderEntriesOf(
Map.of("privateKey", "privateValue1", "anotherPrivateKey", "anotherPrivateValue1"));
}

private void insertAsset(PostgresqlStoreSetupExtension extension, String id) {
var propertiesArray = "[ %s, %s ]".formatted(propertyJsonMap("key", "value" + id), propertyJsonMap("anotherKey", "anotherValue" + id));
var privatePropertiesArray = "[ %s, %s ]".formatted(propertyJsonMap("privateKey", "privateValue" + id), propertyJsonMap("anotherPrivateKey", "anotherPrivateValue" + id));

extension.runQuery(("insert into edc_asset (asset_id, properties, private_properties, data_address) " +
"values ('%s', '%s'::json, '%s'::json, '{\"type\":\"type\"}'::json)")
.formatted(id, propertiesArray, privatePropertiesArray));
}

private String propertyJsonMap(String key, String value) {
return "{\"property_name\" : \"%s\", \"property_value\" : \"%s\", \"property_type\" : \"java.lang.String\"}".formatted(key, value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
package org.eclipse.tractusx.edc.tests.edr;

import jakarta.json.Json;
import okhttp3.mockwebserver.MockWebServer;
import org.assertj.core.api.Condition;
import org.eclipse.edc.policy.model.Operator;
import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -50,12 +46,6 @@ public abstract class AbstractDeleteEdrTest {
.name(PLATO_NAME)
.id(PLATO_BPN)
.build();
MockWebServer server;

@BeforeEach
void setup() {
server = new MockWebServer();
}

@Test
@DisplayName("Verify that expired EDR are deleted")
Expand Down Expand Up @@ -104,14 +94,4 @@ void negotiateEdr_shouldRemoveExpiredEdrs() throws IOException {

}

@AfterEach
void teardown() throws IOException {
server.shutdown();
}


private Condition<String> stateCondition(String value, String description) {
return new Condition<>(m -> m.equals(value), description);
}

}
60 changes: 31 additions & 29 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ format.version = "1.1"

[versions]
edc = "0.5.1-20240131-SNAPSHOT"
postgres = "42.7.1"
apache-sshd = "2.12.0"
assertj = "3.25.3"
awaitility = "4.2.0"
nimbus = "9.37.3"
aws = "2.23.17"
azure-identity = "1.11.1"
slf4j = "2.0.11"
okhttp = "4.12.0"
mockwebserver = "5.0.0-alpha.12"
bouncyCastle-jdk18on = "1.77"
restAssured = "5.4.0"
apache-sshd = "2.12.0"
testcontainers = "1.19.4"
aws = "2.23.17"
rsApi = "3.1.0"
jupiter = "5.10.2"
assertj = "3.25.3"
titanium = "1.3.3"
flyway = "9.22.3"
iron-vc = "0.8.1"
jackson = "2.16.1"
jakarta-json = "2.0.1"
jupiter = "5.10.2"
mockwebserver = "5.0.0-alpha.12"
nimbus = "9.37.3"
okhttp = "4.12.0"
postgres = "42.7.1"
restAssured = "5.4.0"
rsApi = "3.1.0"
slf4j = "2.0.11"
testcontainers = "1.19.4"
tink = "1.12.0"
iron-vc = "0.8.1"
titanium = "1.3.3"

[libraries]
edc-spi-catalog = { module = "org.eclipse.edc:catalog-spi", version.ref = "edc" }
Expand Down Expand Up @@ -162,30 +163,31 @@ edc-transfer-receiver = { module = "org.eclipse.edc:transfer-pull-http-receiver"

# other deps

postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" }
apache-sshd-core = { module = "org.apache.sshd:sshd-core", version.ref = "apache-sshd" }
apache-sshd-sftp = { module = "org.apache.sshd:sshd-sftp", version.ref = "apache-sshd" }
apicatalog-iron-vc = { module = "com.apicatalog:iron-verifiable-credentials", version.ref = "iron-vc" }
assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" }
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
aws-s3 = { module = "software.amazon.awssdk:s3", version.ref = "aws" }
aws-s3transfer = { module = "software.amazon.awssdk:s3-transfer-manager", version.ref = "aws" }
bouncyCastle-bcpkixJdk18on = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bouncyCastle-jdk18on" }
flyway-core = { module = "org.flywaydb:flyway-core", version.ref = "flyway" }
jackson-datatypeJsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
jacksonJsonP = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp", version.ref = "jackson" }
jakarta-rsApi = { module = "jakarta.ws.rs:jakarta.ws.rs-api", version.ref = "rsApi" }
jakartaJson = { module = "org.glassfish:jakarta.json", version.ref = "jakarta-json" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "jupiter" }
nimbus-jwt = { module = "com.nimbusds:nimbus-jose-jwt", version.ref = "nimbus" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" }
bouncyCastle-bcpkixJdk18on = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bouncyCastle-jdk18on" }
postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" }
restAssured = { module = "io.rest-assured:rest-assured", version.ref = "restAssured" }
apache-sshd-core = { module = "org.apache.sshd:sshd-core", version.ref = "apache-sshd" }
apache-sshd-sftp = { module = "org.apache.sshd:sshd-sftp", version.ref = "apache-sshd" }
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
testcontainers-junit = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" }
testcontainers-postgres = { module = "org.testcontainers:postgresql", version.ref = "testcontainers" }
testcontainers-vault = { module = "org.testcontainers:vault", version.ref = "testcontainers" }
aws-s3 = { module = "software.amazon.awssdk:s3", version.ref = "aws" }
aws-s3transfer = { module = "software.amazon.awssdk:s3-transfer-manager", version.ref = "aws" }
jakarta-rsApi = { module = "jakarta.ws.rs:jakarta.ws.rs-api", version.ref = "rsApi" }
jakartaJson = { module = "org.glassfish:jakarta.json", version.ref = "jakarta-json" }
jacksonJsonP = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp", version.ref = "jackson" }
jackson-datatypeJsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
titaniumJsonLd = { module = "com.apicatalog:titanium-json-ld", version.ref = "titanium" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "jupiter" }
assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
tink = { module = "com.google.crypto.tink:tink", version.ref = "tink" }
apicatalog-iron-vc = { module = "com.apicatalog:iron-verifiable-credentials", version.ref = "iron-vc" }
titaniumJsonLd = { module = "com.apicatalog:titanium-json-ld", version.ref = "titanium" }

[bundles]
edc-connector = ["edc.boot", "edc.core-connector", "edc.core-controlplane", "edc.api-observability"]
Expand Down

0 comments on commit 7b0ad5b

Please sign in to comment.