From 77c0ef9e5e8a2386c91f1d621e58b88b53d21e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hermann?= Date: Tue, 15 Oct 2024 15:55:07 -0400 Subject: [PATCH] reusable quarkus-flyway logic --- docs/src/main/asciidoc/flyway.adoc | 90 +++++ .../FlywayMultiTenantCallbacksLocator.java | 105 ------ ...led.java => FlywayMultiTenantEnabled.java} | 4 +- .../FlywayMultiTenantProcessor.java | 350 ++---------------- .../devui/FlywayDevUIProcessor.java | 52 --- .../java/db/migration/V1_0_1__Update.java | 18 - .../java/db/migration/V1_0_2__Update.java | 39 -- .../multitenant/test/DevModeTestEndpoint.java | 22 -- .../FlywayDevModeCreateFromHibernateTest.java | 113 ------ .../FlywayDevModeModifyMigrationTest.java | 58 --- .../multitenant/test/FlywayDevModeTest.java | 43 --- ...AtStartExistingSchemaHistoryTableTest.java | 40 -- .../FlywayExtensionBaselineAtStartTest.java | 39 -- ...nBaselineOnMigrateNamedDataSourceTest.java | 43 --- ...OnMigrateNamedDataSourcesInactiveTest.java | 70 ---- .../FlywayExtensionBaselineOnMigrateTest.java | 41 -- .../test/FlywayExtensionCDICallback.java | 48 --- .../test/FlywayExtensionCallback.java | 47 --- .../test/FlywayExtensionCallback2.java | 39 -- .../test/FlywayExtensionCallbackTest.java | 66 ---- ...ayExtensionCleanAndMigrateAtStartTest.java | 50 --- ...ndMigrateAtStartWithJavaMigrationTest.java | 86 ----- .../test/FlywayExtensionCleanAtStartTest.java | 51 --- ...DefaultDatasourceDynamicInjectionTest.java | 38 -- ...eDefaultDatasourceStaticInjectionTest.java | 46 --- ...seNamedDataSourceDynamicInjectionTest.java | 49 --- ...lseNamedDataSourceStaticInjectionTest.java | 57 --- ...yExtensionConfigDefaultDataSourceTest.java | 35 -- ...figDefaultDataSourceWithoutFlywayTest.java | 38 -- .../test/FlywayExtensionConfigFixture.java | 186 ---------- ...ayExtensionConfigMultiDataSourcesTest.java | 72 ---- ...figMultiDataSourcesWithoutDefaultTest.java | 50 --- ...nfigNamedDataSourceWithoutDefaultTest.java | 39 -- ...onfigNamedDataSourceWithoutFlywayTest.java | 40 -- ...DefaultDatasourceDynamicInjectionTest.java | 38 -- ...gDefaultDatasourceStaticInjectionTest.java | 45 --- ...ngNamedDataSourceDynamicInjectionTest.java | 48 --- ...ingNamedDataSourceStaticInjectionTest.java | 56 --- .../test/FlywayExtensionDisabledTest.java | 31 -- ...FlywayExtensionFilesystemResourceTest.java | 60 --- .../test/FlywayExtensionInitSqlTest.java | 44 --- ...efaultDatasourceConfigActiveFalseTest.java | 42 --- ...tStartDefaultDatasourceUrlMissingTest.java | 41 -- ...sionMigrateAtStartNamedDataSourceTest.java | 44 --- ...tNamedDatasourceConfigActiveFalseTest.java | 52 --- ...rtNamedDatasourceConfigUrlMissingTest.java | 51 --- ...yExtensionMigrateAtStartSubfolderTest.java | 39 -- .../FlywayExtensionMigrateAtStartTest.java | 39 -- .../FlywayExtensionRepairAtStartTest.java | 81 ---- .../FlywayExtensionValidateAtStartTest.java | 23 -- .../FlywayExtensionWithCustomizerTest.java | 66 ---- ...ExtensionWithJavaMigrationDevModeTest.java | 40 -- ...nWithJavaMigrationDevModeTestEndpoint.java | 37 -- ...MultipleDatasourcesAndCustomizersTest.java | 113 ------ .../test/FlywayH2TestCustomizer.java | 81 ---- .../FlywayMultiDataSourcesDevModeTest.java | 35 -- .../flyway/multitenant/test/Fruit.java | 35 -- .../test/MigrateAtStartMultiTenancyTest.java | 117 ++++++ .../test/MultiDataSourcesDevModeEndpoint.java | 50 --- .../test/NamedPersistenceUnitTest.java | 112 ++++++ .../multitenant/test/NoMultiTenancyTest.java | 93 +++++ .../test/SchemaMultiTenancyTest.java | 112 ++++++ ...ing-schema-history-table-config.properties | 8 - ...ine-on-migrate-named-datasource.properties | 10 - ...rate-named-datasources-inactive.properties | 24 -- .../resources/baseline-on-migrate.properties | 10 - .../test/resources/callback-config.properties | 10 - .../src/test/resources/callback-init-data.sql | 4 - ...ean-and-migrate-at-start-config.properties | 13 - ...t-start-with-fs-resource-config.properties | 13 - .../clean-at-start-config.properties | 14 - .../test/resources/config-empty.properties | 1 - ...tasource-with-customizer-config.properties | 9 - ...fault-datasource-without-flyway.properties | 4 - .../config-for-default-datasource.properties | 19 - ...ig-for-missing-named-datasource.properties | 19 - ...asource-with-customizers-config.properties | 24 -- ...ple-datasources-without-default.properties | 41 -- ...config-for-multiple-datasources.properties | 61 --- ...amed-datasource-without-default.properties | 19 - ...named-datasource-without-flyway.properties | 4 - .../subfolder/V1.0.0__Quarkus.sql | 5 - .../db/migration/V1.0.0__Quarkus.sql | 2 +- .../db/migration/V1.0.3__Quarkus_Callback.sql | 4 - .../test/resources/disabled-config.properties | 8 - .../src/test/resources/h2-init-data.sql | 3 - .../h2-init-schema-history-table.sql | 13 - .../test/resources/init-sql-config.properties | 8 - ...t-start-config-named-datasource.properties | 8 - .../migrate-at-start-config.properties | 7 - ... migrate-at-start-multitenancy.properties} | 6 +- ...grate-at-start-subfolder-config.properties | 8 - .../named-peristence-unit.properties | 12 + .../test/resources/no-multitenancy.properties | 8 + .../repair-at-start-config.properties | 7 - .../resources/schema-multitenancy.properties | 10 + .../validate-at-start-config.properties | 7 - extensions/flyway-multitenant/runtime/pom.xml | 2 +- .../FlywayMultiTenantBuildTimeConfig.java | 2 +- .../FlywayMultiTenantContainerProducer.java | 86 ++--- .../FlywayMultiTenantContainerUtil.java | 4 +- .../{ => runtime}/FlywayPersistenceUnit.java | 9 +- .../multitenant/runtime/FlywayRecorder.java | 184 --------- .../runtime/devui/FlywayDevUIRecorder.java | 20 - .../runtime/devui/FlywayJsonRpcService.java | 231 ------------ .../resources/META-INF/quarkus-extension.yaml | 4 +- .../runtime/FlywayCreatorTest.java | 295 --------------- .../flyway/deployment/FlywayBuildItem.java | 70 ++++ .../deployment/FlywayCallbacksLocator.java | 23 +- .../flyway/deployment/FlywayProcessor.java | 137 +++---- .../quarkus/flyway/FlywayTenantSupport.java | 8 + .../flyway/runtime/ContainerProducer.java | 20 + .../flyway/runtime/FlywayContainer.java | 29 +- .../runtime/FlywayContainerProducer.java | 58 ++- .../quarkus/flyway/runtime/FlywayCreator.java | 8 +- .../flyway/runtime/FlywayRecorder.java | 83 +++-- ...UnconfiguredDataSourceFlywayContainer.java | 4 +- 117 files changed, 933 insertions(+), 4556 deletions(-) delete mode 100644 extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantCallbacksLocator.java rename extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/{FlywayEnabled.java => FlywayMultiTenantEnabled.java} (76%) delete mode 100644 extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/devui/FlywayDevUIProcessor.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_1__Update.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_2__Update.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/DevModeTestEndpoint.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeCreateFromHibernateTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeModifyMigrationTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourceTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCDICallback.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback2.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallbackTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartWithJavaMigrationTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAtStartTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceDynamicInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceStaticInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceDynamicInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceStaticInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceWithoutFlywayTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigFixture.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesWithoutDefaultTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutDefaultTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutFlywayTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceDynamicInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceStaticInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceDynamicInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceStaticInjectionTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionDisabledTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionFilesystemResourceTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionInitSqlTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceUrlMissingTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDataSourceTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigUrlMissingTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartSubfolderTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionRepairAtStartTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionValidateAtStartTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithCustomizerTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTestEndpoint.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithMultipleDatasourcesAndCustomizersTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayH2TestCustomizer.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayMultiDataSourcesDevModeTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/Fruit.java create mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MigrateAtStartMultiTenancyTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MultiDataSourcesDevModeEndpoint.java create mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NamedPersistenceUnitTest.java create mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NoMultiTenancyTest.java create mode 100644 extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/SchemaMultiTenancyTest.java delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasource.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/callback-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/callback-init-data.sql delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-with-fs-resource-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/clean-at-start-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-empty.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-with-customizer-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-without-flyway.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-missing-named-datasource.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasource-with-customizers-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources-without-default.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-default.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-flyway.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/db/migration-subfolder/subfolder/V1.0.0__Quarkus.sql delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.3__Quarkus_Callback.sql delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/disabled-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/h2-init-data.sql delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/h2-init-schema-history-table.sql delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/init-sql-config.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config-named-datasource.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config.properties rename extensions/flyway-multitenant/deployment/src/test/resources/{baseline-at-start-config.properties => migrate-at-start-multitenancy.properties} (59%) delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-subfolder-config.properties create mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/named-peristence-unit.properties create mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/no-multitenancy.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/repair-at-start-config.properties create mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/schema-multitenancy.properties delete mode 100644 extensions/flyway-multitenant/deployment/src/test/resources/validate-at-start-config.properties rename extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/{ => runtime}/FlywayPersistenceUnit.java (88%) delete mode 100644 extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayRecorder.java delete mode 100644 extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayDevUIRecorder.java delete mode 100644 extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayJsonRpcService.java delete mode 100644 extensions/flyway-multitenant/runtime/src/test/java/io/quarkus/flyway/multitenant/runtime/FlywayCreatorTest.java create mode 100644 extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayBuildItem.java create mode 100644 extensions/flyway/runtime/src/main/java/io/quarkus/flyway/FlywayTenantSupport.java create mode 100644 extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/ContainerProducer.java diff --git a/docs/src/main/asciidoc/flyway.adoc b/docs/src/main/asciidoc/flyway.adoc index cf2ed63da0a10..1c62006a3d640 100644 --- a/docs/src/main/asciidoc/flyway.adoc +++ b/docs/src/main/asciidoc/flyway.adoc @@ -390,6 +390,96 @@ When using Flyway together with Hibernate ORM, you can use the Dev UI to generat You can find more information about this feature in the xref:hibernate-orm.adoc#flyway[Hibernate ORM guide]. [[reactive-datasources]] + +== Flyway and Hibernate Multitenancy + +To enable the flyway multitenancy support, you need to add the `quarkus-flyway-multitenant` extension to your project. + +[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] +.pom.xml +---- + + io.quarkus + quarkus-flyway-multitenant + +---- + +you can then use the `@FlywayPersistenceUnit` annotation to inject the Flyway object for a specific tenant. + +[source,java] +---- +@ApplicationScoped +public class MigrationService { + + @Inject + @FlywayPersistenceUnit(tenantId = "tenant1") + Flyway flywayForTenant1; <1> + + @Inject + @FlywayPersistenceUnit(value="inventory", tenantId = "tenant1") + Flyway flywayForTenant1OnInventory; <2> + + @Inject + @FlywayPersistenceUnit(value="inventory") + FlywayContainer flywayContainer; <3> + + + public void migrateTenant2() { + flywayContainer.getFlyway("tenant2").migrate(); + } +} +---- +<1> Inject the Flyway object for a specific tenant +<2> Inject Flyway for named persistence unit using the Quarkus `FlywayPersistenceUnit` qualifier +<3> Inject Flyway container for named persistence unit + +It is also possible to specify the list of tenants to be migrated at startup when the `quarkus.flyway.multitenant.migrate-at-start` property is enabled by implementing the FlywayTenantSupport interface. + +[source,java] +---- + @ApplicationScoped + @FlywayPersistenceUnit(value="inventory") + public static class TenantToInitialize implements FlywayTenantSupport { + + @Override + public List getTenantsToInitialize() { + return List.of("tenant1", "tenant2"); + } + } +---- + +It is also possible to use a decorator to automatically run the Flyway migration when the tenant is resolved. + +[source,java] +---- +@Decorator +@Priority(10) +public class FlywayTenantResolverDecorator implements TenantResolver { + + @Inject + @Delegate + @Any + TenantResolver tenantResolver; + + @Inject + @FlywayPersistenceUnit() + FlywayContainer flywayContainer; + + @Override + public String getDefaultTenantId() { + return tenantResolver.getDefaultTenantId(); + } + + @Override + public String resolveTenantId() { + String tenantId = tenantResolver.resolveTenantId(); + Flyway flyway = flywayContainer.getFlyway(tenantId); + flyway.migrate(); + return tenantId; + } +} +---- + == Flyway and Reactive datasources Flyway internally relies on a JDBC datasource, diff --git a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantCallbacksLocator.java b/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantCallbacksLocator.java deleted file mode 100644 index 14be0508d114c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantCallbacksLocator.java +++ /dev/null @@ -1,105 +0,0 @@ -package io.quarkus.flyway.multitenant.deployment; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import org.flywaydb.core.api.callback.Callback; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; - -import io.quarkus.deployment.annotations.BuildProducer; -import io.quarkus.deployment.builditem.CombinedIndexBuildItem; -import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; -import io.quarkus.flyway.multitenant.runtime.FlywayMultiTenantBuildTimeConfig; - -/** - * Logic to locate and process Flyway {@link Callback} classes. - * This class also helps to keep the {@link FlywayMultiTenantProcessor} class as lean as possible to make it easier to maintain - */ -class FlywayMultiTenantCallbacksLocator { - private final Collection persistenceUnitNames; - private final FlywayMultiTenantBuildTimeConfig flywayBuildConfig; - private final CombinedIndexBuildItem combinedIndexBuildItem; - private final BuildProducer reflectiveClassProducer; - - private FlywayMultiTenantCallbacksLocator(Collection persistenceUnitNames, - FlywayMultiTenantBuildTimeConfig flywayBuildConfig, - CombinedIndexBuildItem combinedIndexBuildItem, BuildProducer reflectiveClassProducer) { - this.persistenceUnitNames = persistenceUnitNames; - this.flywayBuildConfig = flywayBuildConfig; - this.combinedIndexBuildItem = combinedIndexBuildItem; - this.reflectiveClassProducer = reflectiveClassProducer; - } - - public static FlywayMultiTenantCallbacksLocator with(Collection persistenceUnitNames, - FlywayMultiTenantBuildTimeConfig flywayBuildConfig, - CombinedIndexBuildItem combinedIndexBuildItem, BuildProducer reflectiveClassProducer) { - return new FlywayMultiTenantCallbacksLocator(persistenceUnitNames, flywayBuildConfig, combinedIndexBuildItem, - reflectiveClassProducer); - } - - /** - * Main logic to identify callbacks and return them to be processed by the {@link FlywayMultiTenantProcessor} - * - * @return Map containing the callbacks for each datasource. The datasource name is the map key - * @exception ClassNotFoundException if the {@link Callback} class cannot be located by the Quarkus class loader - * @exception InstantiationException if the {@link Callback} class represents an abstract class. - * @exception InvocationTargetException if the underlying constructor throws an exception. - * @exception IllegalAccessException if the {@link Callback} constructor is enforcing Java language access control - * and the underlying constructor is inaccessible - */ - public Map> getCallbacks() - throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException { - final Map> callbacks = new HashMap<>(); - for (String dataSourceName : persistenceUnitNames) { - final Collection instances = callbacksForPersistenceUnit(dataSourceName); - callbacks.put(dataSourceName, instances); - } - return callbacks; - } - - /** - * - * Reads the configuration, instantiates the {@link Callback} class. Also, adds it to the reflective producer - * - * @return List of callbacks for the datasource - * @exception ClassNotFoundException if the {@link Callback} class cannot be located by the Quarkus class loader - * @exception InstantiationException if the {@link Callback} class represents an abstract class. - * @exception InvocationTargetException if the underlying constructor throws an exception. - * @exception IllegalAccessException if the {@link Callback} constructor is enforcing Java language access control - * and the underlying constructor is inaccessible - */ - private Collection callbacksForPersistenceUnit(String persistenceUnitName) - throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException { - final Optional> callbackConfig = flywayBuildConfig - .getConfigForPersistenceUnitName(persistenceUnitName).callbacks; - if (!callbackConfig.isPresent()) { - return Collections.emptyList(); - } - final Collection callbacks = callbackConfig.get(); - final Collection instances = new ArrayList<>(callbacks.size()); - for (String callback : callbacks) { - final ClassInfo clazz = combinedIndexBuildItem.getIndex().getClassByName(DotName.createSimple(callback)); - Objects.requireNonNull(clazz, - "Flyway callback not found, please verify the fully qualified name for the class: " + callback); - if (Modifier.isAbstract(clazz.flags()) || !clazz.hasNoArgsConstructor()) { - throw new IllegalArgumentException( - "Invalid Flyway callback. It shouldn't be abstract and must have a default constructor"); - } - final Class clazzType = Class.forName(callback, false, Thread.currentThread().getContextClassLoader()); - final Callback instance = (Callback) clazzType.getConstructors()[0].newInstance(); - instances.add(instance); - reflectiveClassProducer - .produce(ReflectiveClassBuildItem.builder(clazz.name().toString()).build()); - } - return instances; - } -} diff --git a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayEnabled.java b/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantEnabled.java similarity index 76% rename from extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayEnabled.java rename to extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantEnabled.java index 904ca4cccb1de..e5a10b17d383b 100644 --- a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayEnabled.java +++ b/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantEnabled.java @@ -8,11 +8,11 @@ * Supplier that can be used to only run build steps * if the Flyway extension is enabled. */ -public class FlywayEnabled implements BooleanSupplier { +public class FlywayMultiTenantEnabled implements BooleanSupplier { private final FlywayMultiTenantBuildTimeConfig config; - FlywayEnabled(FlywayMultiTenantBuildTimeConfig config) { + FlywayMultiTenantEnabled(FlywayMultiTenantBuildTimeConfig config) { this.config = config; } diff --git a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantProcessor.java b/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantProcessor.java index 495d5dc25e79f..de6aa4eb84535 100644 --- a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantProcessor.java +++ b/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/FlywayMultiTenantProcessor.java @@ -1,355 +1,61 @@ package io.quarkus.flyway.multitenant.deployment; import static io.quarkus.datasource.common.runtime.DataSourceUtil.DEFAULT_DATASOURCE_NAME; -import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.AbstractCollection; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import io.quarkus.flyway.multitenant.FlywayPersistenceUnit; -import io.quarkus.flyway.runtime.FlywayContainer; -import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; -import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem; -import io.quarkus.hibernate.orm.runtime.migration.MultiTenancyStrategy; -import jakarta.enterprise.context.Dependent; -import jakarta.enterprise.inject.spi.InjectionPoint; -import jakarta.inject.Singleton; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.Location; -import org.flywaydb.core.api.callback.Callback; -import org.flywaydb.core.api.migration.JavaMigration; import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.ClassType; -import org.jboss.jandex.DotName; import org.jboss.logging.Logger; -import io.quarkus.agroal.runtime.DataSources; -import io.quarkus.agroal.spi.JdbcDataSourceBuildItem; -import io.quarkus.agroal.spi.JdbcDataSourceSchemaReadyBuildItem; -import io.quarkus.agroal.spi.JdbcInitialSQLGeneratorBuildItem; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; -import io.quarkus.arc.deployment.BeanContainerBuildItem; -import io.quarkus.arc.deployment.SyntheticBeanBuildItem; -import io.quarkus.arc.deployment.SyntheticBeansRuntimeInitBuildItem; import io.quarkus.arc.processor.DotNames; -import io.quarkus.builder.item.SimpleBuildItem; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.BuildSteps; -import io.quarkus.deployment.annotations.Consume; -import io.quarkus.deployment.annotations.ExecutionTime; -import io.quarkus.deployment.annotations.Produce; -import io.quarkus.deployment.annotations.Record; -import io.quarkus.deployment.builditem.ApplicationInfoBuildItem; -import io.quarkus.deployment.builditem.CombinedIndexBuildItem; -import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem; -import io.quarkus.deployment.builditem.InitTaskBuildItem; -import io.quarkus.deployment.builditem.InitTaskCompletedBuildItem; -import io.quarkus.deployment.builditem.ServiceStartBuildItem; -import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; -import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; -import io.quarkus.deployment.logging.LoggingSetupBuildItem; -import io.quarkus.deployment.recording.RecorderContext; -import io.quarkus.flyway.FlywayDataSource; +import io.quarkus.flyway.deployment.FlywayBuildItem; import io.quarkus.flyway.multitenant.runtime.FlywayMultiTenantBuildTimeConfig; import io.quarkus.flyway.multitenant.runtime.FlywayMultiTenantContainerProducer; -import io.quarkus.flyway.multitenant.runtime.FlywayRecorder; -import io.quarkus.flyway.multitenant.runtime.FlywayMultiTenantRuntimeConfig; -import io.quarkus.runtime.util.ClassPathUtils; +import io.quarkus.flyway.multitenant.runtime.FlywayPersistenceUnit; +import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; +import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem; +import io.quarkus.hibernate.orm.runtime.migration.MultiTenancyStrategy; -@BuildSteps(onlyIf = FlywayEnabled.class) +@BuildSteps(onlyIf = FlywayMultiTenantEnabled.class) class FlywayMultiTenantProcessor { - private static final String CLASSPATH_APPLICATION_MIGRATIONS_PROTOCOL = "classpath"; - - private static final String FLYWAY_CONTAINER_BEAN_NAME_PREFIX = "flyway_container_"; - private static final String FLYWAY_BEAN_NAME_PREFIX = "flyway_"; - - private static final DotName JAVA_MIGRATION = DotName.createSimple(JavaMigration.class.getName()); + private static final String FLYWAY_CONTAINER_BEAN_NAME_PREFIX = "flyway_multitenant_container_"; + private static final String FLYWAY_BEAN_NAME_PREFIX = "flyway_multitenant_"; private static final Logger LOGGER = Logger.getLogger(FlywayMultiTenantProcessor.class); - @Record(STATIC_INIT) - @BuildStep - MigrationStateBuildItem build(BuildProducer resourceProducer, - BuildProducer reflectiveClassProducer, - BuildProducer hotDeploymentProducer, - FlywayRecorder recorder, - RecorderContext context, - CombinedIndexBuildItem combinedIndexBuildItem, - List jdbcDataSourceBuildItems, - FlywayMultiTenantBuildTimeConfig flywayMultiTenantBuildTimeConfig) throws Exception { - - Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); - Map> applicationMigrationsToDs = new HashMap<>(); - for (var dataSourceName : dataSourceNames) { - FlywayDataSourceBuildTimeConfig flywayPersistenceUnitBuildTimeConfig = flywayMultiTenantBuildTimeConfig - .getConfigForPersistenceUnitName(dataSourceName); - - Collection migrationLocations = discoverApplicationMigrations( - flywayPersistenceUnitBuildTimeConfig.locations); - applicationMigrationsToDs.put(dataSourceName, migrationLocations); - } - Set datasourcesWithMigrations = new HashSet<>(); - Set datasourcesWithoutMigrations = new HashSet<>(); - for (var e : applicationMigrationsToDs.entrySet()) { - if (e.getValue().isEmpty()) { - datasourcesWithoutMigrations.add(e.getKey()); - } else { - datasourcesWithMigrations.add(e.getKey()); - } - } - - Collection applicationMigrations = applicationMigrationsToDs.values().stream().collect(HashSet::new, - AbstractCollection::addAll, HashSet::addAll); - for (String applicationMigration : applicationMigrations) { - Location applicationMigrationLocation = new Location(applicationMigration); - String applicationMigrationPath = applicationMigrationLocation.getPath(); - - if ((applicationMigrationPath != null) && - // we don't include .class files in the watched files because that messes up live reload - !applicationMigrationPath.endsWith(".class")) { - hotDeploymentProducer.produce(new HotDeploymentWatchedFileBuildItem(applicationMigrationPath)); - } - } - recorder.setApplicationMigrationFiles(applicationMigrations); - - Set> javaMigrationClasses = new HashSet<>(); - addJavaMigrations(combinedIndexBuildItem.getIndex().getAllKnownImplementors(JAVA_MIGRATION), context, - reflectiveClassProducer, javaMigrationClasses); - recorder.setApplicationMigrationClasses(javaMigrationClasses); - - final Map> callbacks = FlywayMultiTenantCallbacksLocator.with( - dataSourceNames, - flywayMultiTenantBuildTimeConfig, - combinedIndexBuildItem, - reflectiveClassProducer).getCallbacks(); - recorder.setApplicationCallbackClasses(callbacks); - - resourceProducer.produce(new NativeImageResourceBuildItem(applicationMigrations.toArray(new String[0]))); - return new MigrationStateBuildItem(datasourcesWithMigrations, datasourcesWithoutMigrations); - } - - @SuppressWarnings("unchecked") - private void addJavaMigrations(Collection candidates, RecorderContext context, - BuildProducer reflectiveClassProducer, - Set> javaMigrationClasses) { - for (ClassInfo javaMigration : candidates) { - if (Modifier.isAbstract(javaMigration.flags())) { - continue; - } - javaMigrationClasses.add((Class) context.classProxy(javaMigration.name().toString())); - reflectiveClassProducer.produce( - ReflectiveClassBuildItem.builder(javaMigration.name().toString()).build()); - } - } - @BuildStep - @Produce(SyntheticBeansRuntimeInitBuildItem.class) - @Consume(LoggingSetupBuildItem.class) - @Record(ExecutionTime.RUNTIME_INIT) - void createBeans(FlywayRecorder recorder, - List persistenceUnits, - List sqlGeneratorBuildItems, - BuildProducer additionalBeans, - BuildProducer syntheticBeanBuildItemBuildProducer, - MigrationStateBuildItem migrationsBuildItem, - FlywayMultiTenantBuildTimeConfig flywayMultiTenantBuildTimeConfig) { - // make a FlywayContainerProducer bean - additionalBeans.produce( - AdditionalBeanBuildItem.builder().addBeanClasses(FlywayMultiTenantContainerProducer.class).setUnremovable() - .setDefaultScope(DotNames.SINGLETON).build()); - // add the @FlywayDataSource class otherwise it won't be registered as a qualifier - additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClass(FlywayDataSource.class).build()); - - for (var persistenceUnit : persistenceUnits) { + void prepare(BuildProducer flywayBuildItems, List persistenceUnits, + FlywayMultiTenantBuildTimeConfig flywayBuildTimeConfig) { + for (PersistenceUnitDescriptorBuildItem persistenceUnit : persistenceUnits) { String persistenceUnitName = persistenceUnit.getPersistenceUnitName(); String dataSourceName = persistenceUnit.getConfig().getDataSource().orElse(DEFAULT_DATASOURCE_NAME); - boolean multiTenant = persistenceUnit.getConfig().getMultiTenancyStrategy() == MultiTenancyStrategy.SCHEMA; - - boolean hasMigrations = migrationsBuildItem.hasMigrations.contains(persistenceUnitName); - boolean createPossible = false; - if (!hasMigrations) { - createPossible = sqlGeneratorBuildItems.stream().anyMatch(s -> s.getDatabaseName().equals(persistenceUnitName)); - } - - SyntheticBeanBuildItem.ExtendedBeanConfigurator flywayContainerConfigurator = SyntheticBeanBuildItem - .configure(FlywayContainer.class) - .scope(multiTenant ? Dependent.class : Singleton.class) - .setRuntimeInit() - .unremovable() - .addInjectionPoint(ClassType.create(DotName.createSimple(FlywayMultiTenantContainerProducer.class))) - .addInjectionPoint(ClassType.create(DotName.createSimple(DataSources.class))) - .createWith(recorder.flywayContainerFunction(dataSourceName, persistenceUnitName, multiTenant, - hasMigrations, createPossible)); - - AnnotationInstance flywayContainerQualifier; - - String containerBeanName = FLYWAY_CONTAINER_BEAN_NAME_PREFIX + persistenceUnitName; - flywayContainerConfigurator.name(containerBeanName); - - flywayContainerConfigurator.addQualifier().annotation(DotNames.NAMED).addValue("value", containerBeanName).done(); - flywayContainerConfigurator.addQualifier().annotation(FlywayPersistenceUnit.class) - .addValue("value", persistenceUnitName) - .done(); - flywayContainerConfigurator.priority(5); - - flywayContainerQualifier = AnnotationInstance.builder(FlywayPersistenceUnit.class).add("value", persistenceUnitName) + boolean multiTenancyEnabled = persistenceUnit.getConfig().getMultiTenancyStrategy() == MultiTenancyStrategy.SCHEMA; + FlywayDataSourceBuildTimeConfig buildTimeConfig = flywayBuildTimeConfig + .getConfigForPersistenceUnitName(persistenceUnitName); + AnnotationInstance qualifier = AnnotationInstance.builder(FlywayPersistenceUnit.class) + .add("value", persistenceUnitName) .build(); - - syntheticBeanBuildItemBuildProducer.produce(flywayContainerConfigurator.done()); - - SyntheticBeanBuildItem.ExtendedBeanConfigurator flywayConfigurator = SyntheticBeanBuildItem - .configure(Flyway.class) - .scope(multiTenant ? Dependent.class : Singleton.class) - .setRuntimeInit() - .unremovable() - .addInjectionPoint(ClassType.create(DotName.createSimple(FlywayContainer.class)), flywayContainerQualifier) - .createWith(recorder.flywayFunction(persistenceUnitName, multiTenant)); - - if (multiTenant) { - flywayConfigurator.addInjectionPoint( - ClassType.create(DotName.createSimple(InjectionPoint.class))); - } - String flywayBeanName = FLYWAY_BEAN_NAME_PREFIX + persistenceUnitName; - flywayConfigurator.name(flywayBeanName); - flywayConfigurator.priority(5); - - flywayConfigurator.addQualifier().annotation(DotNames.NAMED).addValue("value", flywayBeanName).done(); - flywayConfigurator.addQualifier().annotation(FlywayPersistenceUnit.class).addValue("value", persistenceUnitName) - .done(); - - syntheticBeanBuildItemBuildProducer.produce(flywayConfigurator.done()); - } - } - - @BuildStep - @Consume(BeanContainerBuildItem.class) - @Record(ExecutionTime.RUNTIME_INIT) - public ServiceStartBuildItem startActions(FlywayRecorder recorder, - FlywayMultiTenantRuntimeConfig config, - BuildProducer schemaReadyBuildItem, - BuildProducer initializationCompleteBuildItem, - List jdbcDataSourceBuildItems, - MigrationStateBuildItem migrationsBuildItem) { - - Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); - - for (String dataSourceName : dataSourceNames) { - recorder.doStartActions(dataSourceName); + String containerBeanName = FLYWAY_CONTAINER_BEAN_NAME_PREFIX + persistenceUnitName; + flywayBuildItems + .produce(new FlywayBuildItem(persistenceUnitName, dataSourceName, multiTenancyEnabled, buildTimeConfig, + qualifier, flywayBeanName, containerBeanName, 5, FlywayMultiTenantContainerProducer.class)); } - - // once we are done running the migrations, we produce a build item indicating that the - // schema is "ready" - schemaReadyBuildItem.produce(new JdbcDataSourceSchemaReadyBuildItem(migrationsBuildItem.hasMigrations)); - initializationCompleteBuildItem.produce(new InitTaskCompletedBuildItem("flyway")); - return new ServiceStartBuildItem("flyway"); } @BuildStep - public InitTaskBuildItem configureInitTask(ApplicationInfoBuildItem app) { - return InitTaskBuildItem.create() - .withName(app.getName() + "-flyway-init") - .withTaskEnvVars(Map.of("QUARKUS_INIT_AND_EXIT", "true", "QUARKUS_FLYWAY_ENABLED", "true")) - .withAppEnvVars(Map.of("QUARKUS_FLYWAY_ENABLED", "false")) - .withSharedEnvironment(true) - .withSharedFilesystem(true); - } - - private Set getDataSourceNames(List jdbcDataSourceBuildItems) { - Set result = new HashSet<>(jdbcDataSourceBuildItems.size()); - for (JdbcDataSourceBuildItem item : jdbcDataSourceBuildItems) { - result.add(item.getName()); - } - return result; - } - - private Collection discoverApplicationMigrations(Collection locations) - throws IOException { - LinkedHashSet applicationMigrationResources = new LinkedHashSet<>(); - // Locations can be a comma separated list - for (String location : locations) { - location = normalizeLocation(location); - if (location.startsWith(Location.FILESYSTEM_PREFIX)) { - applicationMigrationResources.add(location); - continue; - } - - String finalLocation = location; - ClassPathUtils.consumeAsPaths(Thread.currentThread().getContextClassLoader(), location, path -> { - Set applicationMigrations = null; - try { - applicationMigrations = FlywayMultiTenantProcessor.this.getApplicationMigrationsFromPath(finalLocation, - path); - } catch (IOException e) { - LOGGER.warnv(e, - "Can't process files in path %s", path); - } - if (applicationMigrations != null) { - applicationMigrationResources.addAll(applicationMigrations); - } - }); - } - return applicationMigrationResources; - } - - private String normalizeLocation(String location) { - if (location == null) { - throw new IllegalStateException("Flyway migration location may not be null."); - } - - // Strip any 'classpath:' protocol prefixes because they are assumed - // but not recognized by ClassLoader.getResources() - if (location.startsWith(CLASSPATH_APPLICATION_MIGRATIONS_PROTOCOL + ':')) { - location = location.substring(CLASSPATH_APPLICATION_MIGRATIONS_PROTOCOL.length() + 1); - if (location.startsWith("/")) { - location = location.substring(1); - } - } - if (!location.endsWith("/")) { - location += "/"; - } - - return location; - } - - private Set getApplicationMigrationsFromPath(final String location, final Path rootPath) - throws IOException { - - try (final Stream pathStream = Files.walk(rootPath)) { - return pathStream.filter(Files::isRegularFile) - .map(it -> Paths.get(location, rootPath.relativize(it).toString()).normalize().toString()) - // we don't want windows paths here since the paths are going to be used as classpath paths anyway - .map(it -> it.replace('\\', '/')) - .peek(it -> LOGGER.debugf("Discovered path: %s", it)) - .collect(Collectors.toSet()); - } - } - - public static final class MigrationStateBuildItem extends SimpleBuildItem { - - final Set hasMigrations; - final Set missingMigrations; - - MigrationStateBuildItem(Set hasMigrations, Set missingMigrations) { - this.hasMigrations = hasMigrations; - this.missingMigrations = missingMigrations; - } + void createBeans( + BuildProducer additionalBeans) { + // make a FlywayMultiTenantContainerProducer bean + additionalBeans.produce( + AdditionalBeanBuildItem.builder().addBeanClasses(FlywayMultiTenantContainerProducer.class).setUnremovable() + .setDefaultScope(DotNames.SINGLETON).build()); + // add the @FlywayPersistenceUnit class otherwise it won't be registered as a qualifier + additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClass(FlywayPersistenceUnit.class).build()); } } diff --git a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/devui/FlywayDevUIProcessor.java b/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/devui/FlywayDevUIProcessor.java deleted file mode 100644 index 697fee8f13a4e..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/main/java/io/quarkus/flyway/multitenant/deployment/devui/FlywayDevUIProcessor.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.quarkus.flyway.multitenant.deployment.devui; - -import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -import io.quarkus.agroal.spi.JdbcInitialSQLGeneratorBuildItem; -import io.quarkus.deployment.IsDevelopment; -import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.annotations.Record; -import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem; -import io.quarkus.devui.spi.JsonRPCProvidersBuildItem; -import io.quarkus.devui.spi.page.CardPageBuildItem; -import io.quarkus.devui.spi.page.Page; -import io.quarkus.flyway.multitenant.runtime.FlywayMultiTenantBuildTimeConfig; -import io.quarkus.flyway.multitenant.runtime.devui.FlywayDevUIRecorder; -import io.quarkus.flyway.multitenant.runtime.devui.FlywayJsonRpcService; - -public class FlywayDevUIProcessor { - - @BuildStep(onlyIf = IsDevelopment.class) - @Record(value = RUNTIME_INIT, optional = true) - CardPageBuildItem create(FlywayDevUIRecorder recorder, FlywayMultiTenantBuildTimeConfig buildTimeConfig, - List generatorBuildItem, - CurateOutcomeBuildItem curateOutcomeBuildItem) { - - Map> initialSqlSuppliers = new HashMap<>(); - for (JdbcInitialSQLGeneratorBuildItem buildItem : generatorBuildItem) { - initialSqlSuppliers.put(buildItem.getDatabaseName(), buildItem.getSqlSupplier()); - } - - String artifactId = curateOutcomeBuildItem.getApplicationModel().getAppArtifact().getArtifactId(); - - recorder.setInitialSqlSuppliers(initialSqlSuppliers, artifactId); - - CardPageBuildItem card = new CardPageBuildItem(); - - card.addPage(Page.webComponentPageBuilder() - .componentLink("qwc-flyway-datasources.js") - .dynamicLabelJsonRPCMethodName("getNumberOfDatasources") - .icon("font-awesome-solid:database")); - return card; - } - - @BuildStep(onlyIf = IsDevelopment.class) - JsonRPCProvidersBuildItem registerJsonRpcBackend() { - return new JsonRPCProvidersBuildItem(FlywayJsonRpcService.class); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_1__Update.java b/extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_1__Update.java deleted file mode 100644 index 38855b7bd4554..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_1__Update.java +++ /dev/null @@ -1,18 +0,0 @@ -package db.migration; - -import java.sql.Statement; - -import org.flywaydb.core.api.migration.BaseJavaMigration; -import org.flywaydb.core.api.migration.Context; - -/** - * Migration class for some testcases. - */ -public class V1_0_1__Update extends BaseJavaMigration { - @Override - public void migrate(Context context) throws Exception { - try (Statement statement = context.getConnection().createStatement()) { - statement.executeUpdate("INSERT INTO quarked_flyway VALUES (1001, 'test')"); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_2__Update.java b/extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_2__Update.java deleted file mode 100644 index 3181a849404d5..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/db/migration/V1_0_2__Update.java +++ /dev/null @@ -1,39 +0,0 @@ -package db.migration; - -import java.sql.Statement; - -import org.flywaydb.core.api.MigrationVersion; -import org.flywaydb.core.api.migration.Context; -import org.flywaydb.core.api.migration.JavaMigration; - -/** - * Migration class for some testcases. - */ -public class V1_0_2__Update implements JavaMigration { - @Override - public MigrationVersion getVersion() { - return MigrationVersion.fromVersion("1.0.2"); - } - - @Override - public String getDescription() { - return getClass().getSimpleName(); - } - - @Override - public Integer getChecksum() { - return null; - } - - @Override - public boolean canExecuteInTransaction() { - return true; - } - - @Override - public void migrate(Context context) throws Exception { - try (Statement statement = context.getConnection().createStatement()) { - statement.executeUpdate("INSERT INTO quarked_flyway VALUES (1002, 'test')"); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/DevModeTestEndpoint.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/DevModeTestEndpoint.java deleted file mode 100644 index 3c540864967bf..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/DevModeTestEndpoint.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; - -import org.flywaydb.core.Flyway; - -@Path("/fly") -public class DevModeTestEndpoint { - - @Inject - Instance flyway; - - @GET - public boolean present() { - flyway.get(); - return true; - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeCreateFromHibernateTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeCreateFromHibernateTest.java deleted file mode 100644 index 3e7c3407d17be..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeCreateFromHibernateTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import jakarta.annotation.PostConstruct; -import jakarta.inject.Inject; -import jakarta.persistence.EntityManager; -import jakarta.transaction.Transactional; -import jakarta.transaction.UserTransaction; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; - -import org.hamcrest.CoreMatchers; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.StringAsset; -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import com.fasterxml.jackson.databind.JsonNode; - -import io.quarkus.devui.tests.DevUIJsonRPCTest; -import io.quarkus.runtime.Startup; -import io.quarkus.test.QuarkusDevModeTest; -import io.restassured.RestAssured; - -public class FlywayDevModeCreateFromHibernateTest extends DevUIJsonRPCTest { - - public FlywayDevModeCreateFromHibernateTest() { - super("io.quarkus.quarkus-flyway"); - } - - @RegisterExtension - static final QuarkusDevModeTest config = new QuarkusDevModeTest() - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addClasses(FlywayDevModeCreateFromHibernateTest.class, Endpoint.class, Fruit.class) - .addAsResource(new StringAsset( - "quarkus.flyway.locations=db/create"), "application.properties")); - - @Test - public void testGenerateMigrationFromHibernate() throws Exception { - RestAssured.get("fruit").then().statusCode(200) - .body("[0].name", CoreMatchers.is("Orange")); - - Map params = Map.of("ds", ""); - JsonNode devuiresponse = super.executeJsonRPCMethod("create", params); - - Assertions.assertNotNull(devuiresponse); - String type = devuiresponse.get("type").asText(); - Assertions.assertNotNull(type); - Assertions.assertEquals("success", type); - - config.modifySourceFile(Fruit.class, s -> s.replace("Fruit {", "Fruit {\n" + - " \n" + - " private String color;\n" + - "\n" + - " public String getColor() {\n" + - " return color;\n" + - " }\n" + - "\n" + - " public Fruit setColor(String color) {\n" + - " this.color = color;\n" + - " return this;\n" + - " }")); - //added a field, should now fail (if hibernate were still in charge this would work) - RestAssured.get("fruit").then().statusCode(500); - //now update out sql - config.modifyResourceFile("db/create/V1.0.0__quarkus-flyway-deployment.sql", new Function() { - @Override - public String apply(String s) { - return s + "\nalter table FRUIT add column color VARCHAR;"; - } - }); - // TODO: This still fails. - // RestAssured.get("fruit").then().statusCode(200) - // .body("[0].name", CoreMatchers.is("Orange")); - } - - @Path("/fruit") - @Startup - public static class Endpoint { - - @Inject - EntityManager entityManager; - - @Inject - UserTransaction tx; - - @GET - public List list() { - return entityManager.createQuery("from Fruit", Fruit.class).getResultList(); - } - - @PostConstruct - @Transactional - public void add() throws Exception { - tx.begin(); - try { - Fruit f = new Fruit(); - f.setName("Orange"); - entityManager.persist(f); - tx.commit(); - } catch (Exception e) { - tx.rollback(); - throw e; - } - } - - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeModifyMigrationTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeModifyMigrationTest.java deleted file mode 100644 index df566757ff467..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeModifyMigrationTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.hamcrest.Matchers.is; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.function.Function; - -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.agroal.api.AgroalDataSource; -import io.quarkus.test.QuarkusDevModeTest; -import io.restassured.RestAssured; - -public class FlywayDevModeModifyMigrationTest { - - @RegisterExtension - static final QuarkusDevModeTest config = new QuarkusDevModeTest() - .withApplicationRoot((jar) -> jar - .addClasses(RowCountEndpoint.class) - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("clean-and-migrate-at-start-config.properties", "application.properties")); - - @Test - public void testModifyingExistingMigrationScriptCausesRestart() { - RestAssured.get("/row-count").then().statusCode(200).body(is("0")); - config.modifyResourceFile("db/migration/V1.0.0__Quarkus.sql", new Function() { - @Override - public String apply(String s) { - return s + '\n' + "INSERT INTO quarked_flyway VALUES (1001, 'test')"; - } - }); - RestAssured.get("/row-count").then().statusCode(200).body(is("1")); - } - - @Path("/row-count") - public static class RowCountEndpoint { - - @Inject - AgroalDataSource dataSource; - - @GET - public int rowCount() throws SQLException { - try (Connection connection = dataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet countQuery = stat.executeQuery("select count(1) from quarked_flyway")) { - return countQuery.first() ? countQuery.getInt(1) : 0; - } - } - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeTest.java deleted file mode 100644 index e8a3540d38174..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayDevModeTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.util.function.Function; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusDevModeTest; -import io.restassured.RestAssured; - -/** - * Flyway needs a datasource to work. - * This tests assures, that an error occurs, - * as soon as the default flyway configuration points to a missing default datasource. - */ -public class FlywayDevModeTest { - - @RegisterExtension - static final QuarkusDevModeTest config = new QuarkusDevModeTest() - .withApplicationRoot((jar) -> jar - .addClasses(DevModeTestEndpoint.class) - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("config-empty.properties", "application.properties")); - - @Test - @DisplayName("Injecting (default) flyway should fail if there is no datasource configured") - public void testAddingFlyway() { - RestAssured.get("fly").then().statusCode(500); - config.modifyResourceFile("application.properties", new Function() { - @Override - public String apply(String s) { - return "quarkus.datasource.db-kind=h2\n" + - "quarkus.datasource.username=sa\n" + - "quarkus.datasource.password=sa\n" + - "quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-dev-mode;DB_CLOSE_DELAY=-1\n" + - "quarkus.flyway.migrate-at-start=true"; - } - }); - RestAssured.get("/fly").then().statusCode(200); - - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java deleted file mode 100644 index 40128c14eaaad..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertNull; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest { - @Inject - Flyway flyway; - - static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer - .withDbName("quarkus-baseline-at-start-existing-schema-history") - .withPort(11309) - .withInitSqlFile("src/test/resources/h2-init-schema-history-table.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(customizer::startH2) - .setAfterAllCustomizer(customizer::stopH2) - .withApplicationRoot((jar) -> jar - .addClass(FlywayH2TestCustomizer.class) - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("baseline-at-start-existing-schema-history-table-config.properties", - "application.properties")); - - @Test - @DisplayName("Baseline at start is not executed against existing schema-history-table") - public void testFlywayConfigInjection() { - MigrationInfo migrationInfo = flyway.info().current(); - assertNull(migrationInfo, "Flyway baseline was executed on existing schema history table"); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartTest.java deleted file mode 100644 index c917e7ce8c02f..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineAtStartTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionBaselineAtStartTest { - @Inject - Flyway flyway; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("baseline-at-start-config.properties", "application.properties")); - - @Test - @DisplayName("Baseline at start is executed against empty schema") - public void testFlywayConfigInjection() { - MigrationInfo migrationInfo = flyway.info().current(); - assertNotNull(migrationInfo, "No Flyway migration was executed"); - assertTrue(migrationInfo.getType().isBaseline(), "Flyway migration is not a baseline"); - String currentVersion = migrationInfo - .getVersion() - .toString(); - - assertEquals("1.0.1", currentVersion); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourceTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourceTest.java deleted file mode 100644 index ccf8b2999e6c9..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourceTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionBaselineOnMigrateNamedDataSourceTest { - - @Inject - @FlywayDataSource("users") - Flyway flyway; - - static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer - .withDbName("quarkus-flyway-baseline-on-named-ds") - .withPort(11302) - .withInitSqlFile("src/test/resources/h2-init-data.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(customizer::startH2) - .setAfterAllCustomizer(customizer::stopH2) - .withApplicationRoot((jar) -> jar - .addClass(FlywayH2TestCustomizer.class) - .addAsResource("baseline-on-migrate-named-datasource.properties", "application.properties")); - - @Test - @DisplayName("Create history table correctly") - public void testFlywayInitialBaselineInfo() { - MigrationInfo baselineInfo = flyway.info().applied()[0]; - - assertEquals("0.0.1", baselineInfo.getVersion().getVersion()); - assertEquals("Initial description for test", baselineInfo.getDescription()); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java deleted file mode 100644 index d7212a5fa6648..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest { - - @Inject - @FlywayDataSource("users") - Flyway flywayUsers; - - @Inject - @FlywayDataSource("laptops") - Flyway flywayLaptops; - - static final FlywayH2TestCustomizer customizerUsers = FlywayH2TestCustomizer - .withDbName("quarkus-flyway-baseline-on-named-ds-users") - .withPort(11302) - .withInitSqlFile("src/test/resources/h2-init-data.sql"); - - static final FlywayH2TestCustomizer customizerLaptops = FlywayH2TestCustomizer - .withDbName("quarkus-flyway-baseline-on-named-ds-laptops") - .withPort(11303) - .withInitSqlFile("src/test/resources/h2-init-data.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(new Runnable() { - @Override - public void run() { - customizerUsers.startH2(); - customizerLaptops.startH2(); - } - }) - .setAfterAllCustomizer(new Runnable() { - @Override - public void run() { - customizerUsers.stopH2(); - customizerLaptops.stopH2(); - } - }) - .withApplicationRoot((jar) -> jar - .addClass(FlywayH2TestCustomizer.class) - .addAsResource("baseline-on-migrate-named-datasources-inactive.properties", "application.properties")); - - @Test - @DisplayName("Create history table correctly") - public void testFlywayInitialBaselineInfo() { - MigrationInfo baselineInfo = flywayUsers.info().applied()[0]; - - assertEquals("0.0.1", baselineInfo.getVersion().getVersion()); - assertEquals("Initial description for test", baselineInfo.getDescription()); - } - - @Test - @DisplayName("History table not created if inactive") - public void testFlywayInitialBaselineInfoInactive() { - assertEquals(0, flywayLaptops.info().applied().length); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateTest.java deleted file mode 100644 index ef7ab233c6b78..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionBaselineOnMigrateTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionBaselineOnMigrateTest { - - @Inject - Flyway flyway; - - static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer - .withDbName("quarkus-flyway-baseline-on-migrate") - .withPort(11301) - .withInitSqlFile("src/test/resources/h2-init-data.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(customizer::startH2) - .setAfterAllCustomizer(customizer::stopH2) - .withApplicationRoot((jar) -> jar - .addClass(FlywayH2TestCustomizer.class) - .addAsResource("baseline-on-migrate.properties", "application.properties")); - - @Test - @DisplayName("Create history table correctly") - public void testFlywayInitialBaselineInfo() { - MigrationInfo baselineInfo = flyway.info().applied()[0]; - - assertEquals("0.0.1", baselineInfo.getVersion().getVersion()); - assertEquals("Initial description for test", baselineInfo.getDescription()); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCDICallback.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCDICallback.java deleted file mode 100644 index 8f551fbd4cdb5..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCDICallback.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.util.Arrays; -import java.util.List; - -import jakarta.enterprise.inject.spi.CDI; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.callback.Callback; -import org.flywaydb.core.api.callback.Context; -import org.flywaydb.core.api.callback.Event; - -public class FlywayExtensionCDICallback implements Callback { - - public static List DEFAULT_EVENTS = Arrays.asList( - Event.BEFORE_BASELINE, - Event.AFTER_BASELINE, - Event.BEFORE_MIGRATE, - Event.BEFORE_EACH_MIGRATE, - Event.AFTER_EACH_MIGRATE, - Event.AFTER_VERSIONED, - Event.AFTER_MIGRATE, - Event.AFTER_MIGRATE_OPERATION_FINISH); - - @Override - public boolean supports(Event event, Context context) { - return DEFAULT_EVENTS.contains(event); - } - - @Override - public boolean canHandleInTransaction(Event event, Context context) { - return true; - } - - @Override - public void handle(Event event, Context context) { - try { - CDI.current().select(Flyway.class).get(); - } catch (Exception exception) { - throw new IllegalStateException(exception); - } - } - - @Override - public String getCallbackName() { - return "Quarked Flyway Callback with CDI"; - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback.java deleted file mode 100644 index 7dcc7228063af..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Arrays; -import java.util.List; - -import org.flywaydb.core.api.callback.Callback; -import org.flywaydb.core.api.callback.Context; -import org.flywaydb.core.api.callback.Event; - -public class FlywayExtensionCallback implements Callback { - - public static List DEFAULT_EVENTS = Arrays.asList( - Event.BEFORE_BASELINE, - Event.AFTER_BASELINE, - Event.BEFORE_MIGRATE, - Event.BEFORE_EACH_MIGRATE, - Event.AFTER_EACH_MIGRATE, - Event.AFTER_VERSIONED, - Event.AFTER_MIGRATE, - Event.AFTER_MIGRATE_OPERATION_FINISH); - - @Override - public boolean supports(Event event, Context context) { - return DEFAULT_EVENTS.contains(event); - } - - @Override - public boolean canHandleInTransaction(Event event, Context context) { - return true; - } - - @Override - public void handle(Event event, Context context) { - try (Statement stmt = context.getConnection().createStatement()) { - stmt.executeUpdate("INSERT INTO quarked_callback(name) VALUES('" + event.getId() + "')"); - } catch (SQLException exception) { - throw new IllegalStateException(exception); - } - } - - @Override - public String getCallbackName() { - return "Quarked Flyway Callback"; - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback2.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback2.java deleted file mode 100644 index 26875ac9eb24c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallback2.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Arrays; -import java.util.List; - -import org.flywaydb.core.api.callback.Callback; -import org.flywaydb.core.api.callback.Context; -import org.flywaydb.core.api.callback.Event; - -public class FlywayExtensionCallback2 implements Callback { - - public static List DEFAULT_EVENTS = Arrays.asList(Event.AFTER_MIGRATE); - - @Override - public boolean supports(Event event, Context context) { - return DEFAULT_EVENTS.contains(event); - } - - @Override - public boolean canHandleInTransaction(Event event, Context context) { - return true; - } - - @Override - public void handle(Event event, Context context) { - try (Statement stmt = context.getConnection().createStatement()) { - stmt.executeUpdate("INSERT INTO quarked_callback(name) VALUES('" + event.getId() + "')"); - } catch (SQLException exception) { - throw new IllegalStateException(exception); - } - } - - @Override - public String getCallbackName() { - return "Quarked Flyway Callback 2"; - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallbackTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallbackTest.java deleted file mode 100644 index f63702e457fb1..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCallbackTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.agroal.api.AgroalDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionCallbackTest { - - // Quarkus built object - @Inject - Flyway flyway; - - @Inject - AgroalDataSource defaultDataSource; - - static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer - .withDbName("quarkus-flyway-callback") - .withPort(11303) - .withInitSqlFile("src/test/resources/callback-init-data.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(customizer::startH2) - .setAfterAllCustomizer(customizer::stopH2) - .withApplicationRoot((jar) -> jar - .addClasses(FlywayH2TestCustomizer.class, - FlywayExtensionCallback.class, FlywayExtensionCallback2.class, FlywayExtensionCDICallback.class) - .addAsResource("db/migration/V1.0.3__Quarkus_Callback.sql") - .addAsResource("callback-config.properties", "application.properties")); - - @Test - @DisplayName("Migrates at start correctly and executes callback") - public void testFlywayCallback() throws SQLException { - MigrationInfo migrationInfo = flyway.info().current(); - assertNotNull(migrationInfo, "No Flyway migration was executed"); - - String currentVersion = migrationInfo.getVersion().toString(); - // Expected to be 1.0.3 as migration runs at start - assertEquals("1.0.3", currentVersion); - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet executeQuery = stat.executeQuery("select COUNT(name) from quarked_callback")) { - assertTrue(executeQuery.next(), "Table exists but it is empty"); - int count = executeQuery.getInt(1); - // Expect one row for each callback invoked by Flyway - int expected = FlywayExtensionCallback.DEFAULT_EVENTS.size() + FlywayExtensionCallback2.DEFAULT_EVENTS.size(); - assertEquals(expected, count); - } - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartTest.java deleted file mode 100644 index 708999cecb83a..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.h2.jdbc.JdbcSQLSyntaxErrorException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.agroal.api.AgroalDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionCleanAndMigrateAtStartTest { - - @Inject - Flyway flyway; - - @Inject - AgroalDataSource defaultDataSource; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("clean-and-migrate-at-start-config.properties", "application.properties")); - - @Test - @DisplayName("Clean and migrate at start correctly") - public void testFlywayConfigInjection() throws SQLException { - - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet executeQuery = stat.executeQuery("select * from fake_existing_tbl")) { - fail("fake_existing_tbl should not exist"); - } catch (JdbcSQLSyntaxErrorException e) { - // expected fake_existing_tbl does not exist - } - } - String currentVersion = flyway.info().current().getVersion().toString(); - assertEquals("1.0.0", currentVersion, "Expected to be 1.0.0 as migration runs at start"); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartWithJavaMigrationTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartWithJavaMigrationTest.java deleted file mode 100644 index fb9a24c3e55ec..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAndMigrateAtStartWithJavaMigrationTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationVersion; -import org.flywaydb.core.api.migration.Context; -import org.flywaydb.core.api.migration.JavaMigration; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import db.migration.V1_0_1__Update; -import db.migration.V1_0_2__Update; -import io.agroal.api.AgroalDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionCleanAndMigrateAtStartWithJavaMigrationTest { - - @Inject - Flyway flyway; - - @Inject - AgroalDataSource defaultDataSource; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(V1_0_1__Update.class, V1_0_2__Update.class, V9_9_9__Update.class) - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("clean-and-migrate-at-start-config.properties", "application.properties")); - - @Test - @DisplayName("Clean and migrate at start correctly") - public void testFlywayConfigInjection() throws SQLException { - - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet countQuery = stat.executeQuery("select count(1) from quarked_flyway")) { - assertTrue(countQuery.first()); - assertEquals(2, - countQuery.getInt(1), - "Table 'quarked_flyway' does not contain the expected number of rows"); - } - } - String currentVersion = flyway.info().current().getVersion().toString(); - assertEquals("1.0.2", currentVersion, "Expected to be 1.0.2 as there is a SQL and two Java migration scripts"); - } - - public static class V9_9_9__Update implements JavaMigration { - @Override - public MigrationVersion getVersion() { - return MigrationVersion.fromVersion("9.9.9"); - } - - @Override - public String getDescription() { - return getClass().getSimpleName(); - } - - @Override - public Integer getChecksum() { - return null; - } - - @Override - public boolean canExecuteInTransaction() { - return true; - } - - @Override - public void migrate(Context context) throws Exception { - try (Statement statement = context.getConnection().createStatement()) { - statement.executeUpdate("INSERT INTO quarked_flyway VALUES (9999, 'should-not-be-added')"); - } - } - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAtStartTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAtStartTest.java deleted file mode 100644 index 92e7b03ff6f1e..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionCleanAtStartTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.fail; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.h2.jdbc.JdbcSQLSyntaxErrorException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.agroal.api.AgroalDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionCleanAtStartTest { - - @Inject - Flyway flyway; - - @Inject - AgroalDataSource defaultDataSource; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("clean-at-start-config.properties", "application.properties")); - - @Test - @DisplayName("Clean at start correctly") - public void testFlywayConfigInjection() throws SQLException { - - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet executeQuery = stat.executeQuery("select * from fake_existing_tbl")) { - fail("fake_existing_tbl should not exist"); - } catch (JdbcSQLSyntaxErrorException e) { - // expected fake_existing_tbl does not exist - } - } - MigrationInfo current = flyway.info().current(); - assertNull(current, "Info is not null"); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceDynamicInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceDynamicInjectionTest.java deleted file mode 100644 index 3e0267dceba3c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceDynamicInjectionTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigActiveFalseDefaultDatasourceDynamicInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .overrideConfigKey("quarkus.datasource.active", "false"); - - @Inject - Instance flyway; - - @Test - @DisplayName("If the default datasource is deactivated, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource '' for Flyway", - "Datasource '' was deactivated through configuration properties.", - "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", - "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" - + " to 'true' and configure datasource ''", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceStaticInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceStaticInjectionTest.java deleted file mode 100644 index d13f47384f9ec..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseDefaultDatasourceStaticInjectionTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigActiveFalseDefaultDatasourceStaticInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .overrideConfigKey("quarkus.datasource.active", "false"); - - @Inject - MyBean myBean; - - @Test - @DisplayName("If the default datasource is deactivated, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(myBean::useFlyway) - .cause() - .hasMessageContainingAll("Unable to find datasource '' for Flyway", - "Datasource '' was deactivated through configuration properties.", - "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", - "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" - + " to 'true' and configure datasource ''", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - - @ApplicationScoped - public static class MyBean { - @Inject - Flyway flyway; - - public void useFlyway() { - flyway.getConfiguration(); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceDynamicInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceDynamicInjectionTest.java deleted file mode 100644 index ded80952c3b4a..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceDynamicInjectionTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigActiveFalseNamedDataSourceDynamicInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .overrideConfigKey("quarkus.datasource.users.active", "false") - // We need at least one build-time property for the datasource, - // otherwise it's considered unconfigured at build time... - .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") - // We need this otherwise the *default* datasource may impact this test - .overrideConfigKey("quarkus.datasource.db-kind", "h2") - .overrideConfigKey("quarkus.datasource.username", "sa") - .overrideConfigKey("quarkus.datasource.password", "sa") - .overrideConfigKey("quarkus.datasource.jdbc.url", - "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); - - @Inject - @FlywayDataSource("users") - Instance flyway; - - @Test - @DisplayName("If a named datasource is deactivated, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", - "Datasource 'users' was deactivated through configuration properties.", - "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", - "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" - + " to 'true' and configure datasource 'users'", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceStaticInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceStaticInjectionTest.java deleted file mode 100644 index dfdbe367d4ffc..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigActiveFalseNamedDataSourceStaticInjectionTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigActiveFalseNamedDataSourceStaticInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .overrideConfigKey("quarkus.datasource.users.active", "false") - // We need at least one build-time property for the datasource, - // otherwise it's considered unconfigured at build time... - .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") - // We need this otherwise the *default* datasource may impact this test - .overrideConfigKey("quarkus.datasource.db-kind", "h2") - .overrideConfigKey("quarkus.datasource.username", "sa") - .overrideConfigKey("quarkus.datasource.password", "sa") - .overrideConfigKey("quarkus.datasource.jdbc.url", - "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); - - @Inject - MyBean myBean; - - @Test - @DisplayName("If a named datasource is deactivated, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(myBean::useFlyway) - .cause() - .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", - "Datasource 'users' was deactivated through configuration properties.", - "To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).", - "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" - + " to 'true' and configure datasource 'users'", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - - @ApplicationScoped - public static class MyBean { - @Inject - @FlywayDataSource("users") - Flyway flyway; - - public void useFlyway() { - flyway.getConfiguration(); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceTest.java deleted file mode 100644 index 77450ba535768..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigDefaultDataSourceTest { - - @Inject - Flyway flyway; - - @Inject - FlywayExtensionConfigFixture fixture; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClass(FlywayExtensionConfigFixture.class) - .addClasses(FlywayExtensionCallback.class, FlywayExtensionCallback2.class) - .addAsResource("config-for-default-datasource.properties", "application.properties")); - - @Test - @DisplayName("Reads flyway configuration for default datasource correctly") - public void testFlywayConfigInjection() { - fixture.assertAllConfigurationSettings(flyway.getConfiguration(), ""); - assertFalse(fixture.migrateAtStart("")); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceWithoutFlywayTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceWithoutFlywayTest.java deleted file mode 100644 index 2230061e4eb37..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigDefaultDataSourceWithoutFlywayTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -/** - * Assures, that Flyway can also be used without any configuration, - * provided, that at least a datasource is configured. - */ -public class FlywayExtensionConfigDefaultDataSourceWithoutFlywayTest { - - @Inject - Flyway flyway; - - @Inject - FlywayExtensionConfigFixture fixture; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClass(FlywayExtensionConfigFixture.class) - .addAsResource("config-for-default-datasource-without-flyway.properties", "application.properties")); - - @Test - @DisplayName("Reads predefined default flyway configuration for default datasource correctly") - public void testFlywayDefaultConfigInjection() { - fixture.assertDefaultConfigurationSettings(flyway.getConfiguration()); - assertFalse(fixture.migrateAtStart("")); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigFixture.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigFixture.java deleted file mode 100644 index 6f2bfea492925..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigFixture.java +++ /dev/null @@ -1,186 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Arrays; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import org.eclipse.microprofile.config.Config; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.Location; -import org.flywaydb.core.api.configuration.Configuration; -import org.flywaydb.core.api.configuration.FluentConfiguration; - -/** - * This fixture provides access to read the expected and the actual configuration of flyway. - * It also provides a method combining all assertions to be reused for multiple tests. - */ -@ApplicationScoped -public class FlywayExtensionConfigFixture { - - @Inject - Config config; - - public void assertAllConfigurationSettings(Configuration configuration, String dataSourceName) { - assertEquals(locations(configuration), locations(dataSourceName)); - assertEquals(sqlMigrationPrefix(configuration), sqlMigrationPrefix(dataSourceName)); - assertEquals(repeatableSqlMigrationPrefix(configuration), repeatableSqlMigrationPrefix(dataSourceName)); - assertEquals(tableName(configuration), tableName(dataSourceName)); - assertEquals(schemaNames(configuration), schemaNames(dataSourceName)); - - assertEquals(connectRetries(configuration), connectRetries(dataSourceName)); - - assertEquals(baselineOnMigrate(configuration), baselineOnMigrate(dataSourceName)); - assertEquals(baselineVersion(configuration), baselineVersion(dataSourceName)); - assertEquals(baselineDescription(configuration), baselineDescription(dataSourceName)); - assertEquals(callbacks(configuration), callbacks(dataSourceName)); - } - - public void assertDefaultConfigurationSettings(Configuration configuration) { - FluentConfiguration defaultConfiguration = Flyway.configure(); - assertEquals(locations(configuration), locations(defaultConfiguration)); - assertEquals(sqlMigrationPrefix(configuration), sqlMigrationPrefix(defaultConfiguration)); - assertEquals(repeatableSqlMigrationPrefix(configuration), repeatableSqlMigrationPrefix(defaultConfiguration)); - assertEquals(tableName(configuration), tableName(defaultConfiguration)); - assertEquals(schemaNames(configuration), schemaNames(defaultConfiguration)); - - assertEquals(connectRetries(configuration), connectRetries(defaultConfiguration)); - - assertEquals(baselineOnMigrate(configuration), baselineOnMigrate(defaultConfiguration)); - assertEquals(baselineVersion(configuration), baselineVersion(defaultConfiguration)); - assertEquals(baselineDescription(configuration), baselineDescription(defaultConfiguration)); - assertEquals(callbacks(configuration), callbacks(defaultConfiguration)); - } - - public int callbacks(Configuration configuration) { - return configuration.getCallbacks().length; - } - - public int callbacks(String datasourceName) { - return getStringValue("quarkus.flyway.%s.callbacks", datasourceName).split(",").length; - } - - public int connectRetries(String datasourceName) { - return getIntValue("quarkus.flyway.%s.connect-retries", datasourceName); - } - - public int connectRetries(Configuration configuration) { - return configuration.getConnectRetries(); - } - - public String schemaNames(String datasourceName) { - return getStringValue("quarkus.flyway.%s.schemas", datasourceName); - } - - public String schemaNames(Configuration configuration) { - return Arrays.stream(configuration.getSchemas()).collect(Collectors.joining(",")); - } - - public String tableName(String datasourceName) { - return getStringValue("quarkus.flyway.%s.table", datasourceName); - } - - public String tableName(Configuration configuration) { - return configuration.getTable(); - } - - public String locations(String datasourceName) { - return getStringValue("quarkus.flyway.%s.locations", datasourceName); - } - - public String locations(Configuration configuration) { - return Arrays.stream(configuration.getLocations()).map(Location::getPath).collect(Collectors.joining(",")); - } - - public String sqlMigrationPrefix(String datasourceName) { - return getStringValue("quarkus.flyway.%s.sql-migration-prefix", datasourceName); - } - - public String sqlMigrationPrefix(Configuration configuration) { - return configuration.getSqlMigrationPrefix(); - } - - public String repeatableSqlMigrationPrefix(String datasourceName) { - return getStringValue("quarkus.flyway.%s.repeatable-sql-migration-prefix", datasourceName); - } - - public String repeatableSqlMigrationPrefix(Configuration configuration) { - return configuration.getRepeatableSqlMigrationPrefix(); - } - - public boolean baselineOnMigrate(String datasourceName) { - return getBooleanValue("quarkus.flyway.%s.baseline-on-migrate", datasourceName); - } - - public boolean baselineOnMigrate(Configuration configuration) { - return configuration.isBaselineOnMigrate(); - } - - public String baselineVersion(String datasourceName) { - return getStringValue("quarkus.flyway.%s.baseline-version", datasourceName); - } - - public String baselineVersion(Configuration configuration) { - return configuration.getBaselineVersion().getVersion(); - } - - public String baselineDescription(String datasourceName) { - return getStringValue("quarkus.flyway.%s.baseline-description", datasourceName); - } - - public String baselineDescription(Configuration configuration) { - return configuration.getBaselineDescription(); - } - - public boolean migrateAtStart(String datasourceName) { - return getBooleanValue("quarkus.flyway.migrate-at-start", datasourceName); - } - - public String username(String datasourceName) { - return getStringValue("quarkus.flyway.%s.username", datasourceName); - } - - public String password(String datasourceName) { - return getStringValue("quarkus.flyway.%s.password", datasourceName); - } - - public String jdbcUrl(String datasourceName) { - return getStringValue("quarkus.flyway.%s.jdbc-url", datasourceName); - } - - private String getStringValue(String parameterName, String datasourceName) { - return getValue(parameterName, datasourceName, String.class); - } - - private int getIntValue(String parameterName, String datasourceName) { - return getValue(parameterName, datasourceName, Integer.class); - } - - private boolean getBooleanValue(String parameterName, String datasourceName) { - return getValue(parameterName, datasourceName, Boolean.class); - } - - private T getValue(String parameterName, String datasourceName, Class type) { - return getValue(parameterName, datasourceName, type, this::log); - } - - private T getValue(String parameterName, String datasourceName, Class type, Consumer logger) { - String propertyName = fillin(parameterName, datasourceName); - T propertyValue = config.getValue(propertyName, type); - logger.accept("Config property " + propertyName + " = " + propertyValue); - return propertyValue; - } - - private void log(String content) { - //activate for debugging - // System.out.println(content); - } - - private String fillin(String propertyName, String datasourceName) { - return String.format(propertyName, datasourceName).replace("..", "."); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesTest.java deleted file mode 100644 index 29cb982575b25..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import jakarta.inject.Inject; -import jakarta.inject.Named; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -/** - * Test a full configuration with default and two named datasources plus their flyway settings. - */ -public class FlywayExtensionConfigMultiDataSourcesTest { - - @Inject - FlywayExtensionConfigFixture fixture; - - @Inject - Flyway flyway; - - @Inject - @FlywayDataSource("users") - Flyway flywayUsers; - - @Inject - @FlywayDataSource("inventory") - Flyway flywayInventory; - - @Inject - @Named("flyway_inventory") - Flyway flywayNamedInventory; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(FlywayExtensionConfigFixture.class, FlywayExtensionCallback.class) - .addAsResource("config-for-multiple-datasources.properties", "application.properties")); - - @Test - @DisplayName("Reads default flyway configuration for default datasource correctly") - public void testFlywayDefaultConfigInjection() { - fixture.assertAllConfigurationSettings(flyway.getConfiguration(), ""); - assertFalse(fixture.migrateAtStart("")); - } - - @Test - @DisplayName("Reads flyway configuration for datasource named 'users' correctly") - public void testFlywayConfigNamedUsersInjection() { - fixture.assertAllConfigurationSettings(flywayUsers.getConfiguration(), "users"); - assertFalse(fixture.migrateAtStart("")); - } - - @Test - @DisplayName("Reads flyway configuration for datasource named 'inventory' correctly") - public void testFlywayConfigNamedInventoryInjection() { - fixture.assertAllConfigurationSettings(flywayInventory.getConfiguration(), "inventory"); - assertFalse(fixture.migrateAtStart("")); - } - - @Test - @DisplayName("Reads flyway configuration directly named 'inventory_flyway' correctly") - public void testFlywayConfigDirectlyNamedInventoryInjection() { - fixture.assertAllConfigurationSettings(flywayNamedInventory.getConfiguration(), "inventory"); - assertFalse(fixture.migrateAtStart("")); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesWithoutDefaultTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesWithoutDefaultTest.java deleted file mode 100644 index e28d251bd2069..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigMultiDataSourcesWithoutDefaultTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -/** - * Test a full configuration with default and two named datasources plus their flyway settings. - */ -public class FlywayExtensionConfigMultiDataSourcesWithoutDefaultTest { - - @Inject - FlywayExtensionConfigFixture fixture; - - @Inject - @FlywayDataSource("users") - Flyway flywayUsers; - - @Inject - @FlywayDataSource("inventory") - Flyway flywayInventory; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(FlywayExtensionConfigFixture.class, FlywayExtensionCallback.class) - .addAsResource("config-for-multiple-datasources-without-default.properties", "application.properties")); - - @Test - @DisplayName("Reads flyway configuration for datasource named 'users' without default datasource correctly") - public void testFlywayConfigNamedUsersInjection() { - fixture.assertAllConfigurationSettings(flywayUsers.getConfiguration(), "users"); - assertFalse(fixture.migrateAtStart("")); - } - - @Test - @DisplayName("Reads flyway configuration for datasource named 'inventory' without default datasource correctly") - public void testFlywayConfigNamedInventoryInjection() { - fixture.assertAllConfigurationSettings(flywayInventory.getConfiguration(), "inventory"); - assertFalse(fixture.migrateAtStart("")); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutDefaultTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutDefaultTest.java deleted file mode 100644 index c6a9f7e8986dc..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutDefaultTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -/** - * Test a full configuration with default and two named datasources plus their flyway settings. - */ -public class FlywayExtensionConfigNamedDataSourceWithoutDefaultTest { - - @Inject - FlywayExtensionConfigFixture fixture; - - @Inject - @FlywayDataSource("users") - Flyway flywayUsers; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(FlywayExtensionConfigFixture.class, FlywayExtensionCallback.class) - .addAsResource("config-for-named-datasource-without-default.properties", "application.properties")); - - @Test - @DisplayName("Reads flyway configuration for datasource named 'users' without default datasource correctly") - public void testFlywayConfigNamedUsersInjection() { - fixture.assertAllConfigurationSettings(flywayUsers.getConfiguration(), "users"); - assertFalse(fixture.migrateAtStart("")); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutFlywayTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutFlywayTest.java deleted file mode 100644 index f217cf784ddea..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigNamedDataSourceWithoutFlywayTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -/** - * Assures, that flyway can also be used without any configuration, - * provided, that at least a named datasource is configured. - */ -public class FlywayExtensionConfigNamedDataSourceWithoutFlywayTest { - - @Inject - @FlywayDataSource("users") - Flyway flyway; - - @Inject - FlywayExtensionConfigFixture fixture; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClass(FlywayExtensionConfigFixture.class) - .addAsResource("config-for-named-datasource-without-flyway.properties", "application.properties")); - - @Test - @DisplayName("Reads predefined default flyway configuration for named datasource correctly") - public void testFlywayDefaultConfigInjection() { - fixture.assertDefaultConfigurationSettings(flyway.getConfiguration()); - assertFalse(fixture.migrateAtStart("users")); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceDynamicInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceDynamicInjectionTest.java deleted file mode 100644 index 13a93b830e35a..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceDynamicInjectionTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigUrlMissingDefaultDatasourceDynamicInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - // The URL won't be missing if dev services are enabled - .overrideConfigKey("quarkus.devservices.enabled", "false"); - - @Inject - Instance flyway; - - @Test - @DisplayName("If the URL is missing for the default datasource, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource '' for Flyway", - "Datasource '' is not configured.", - "To solve this, configure datasource ''.", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceStaticInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceStaticInjectionTest.java deleted file mode 100644 index 7021d4e8c08f7..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingDefaultDatasourceStaticInjectionTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigUrlMissingDefaultDatasourceStaticInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - // The URL won't be missing if dev services are enabled - .overrideConfigKey("quarkus.devservices.enabled", "false"); - - @Inject - MyBean myBean; - - @Test - @DisplayName("If the URL is missing for the default datasource, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(() -> myBean.useFlyway()) - .cause() - .hasMessageContainingAll("Unable to find datasource '' for Flyway", - "Datasource '' is not configured.", - "To solve this, configure datasource ''.", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - - @ApplicationScoped - public static class MyBean { - @Inject - Flyway flyway; - - public void useFlyway() { - flyway.getConfiguration(); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceDynamicInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceDynamicInjectionTest.java deleted file mode 100644 index 78a9f553c6205..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceDynamicInjectionTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigUrlMissingNamedDataSourceDynamicInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - // The URL won't be missing if dev services are enabled - .overrideConfigKey("quarkus.devservices.enabled", "false") - // We need at least one build-time property for the datasource, - // otherwise it's considered unconfigured at build time... - .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") - // We need this otherwise the *default* datasource may impact this test - .overrideConfigKey("quarkus.datasource.db-kind", "h2") - .overrideConfigKey("quarkus.datasource.username", "sa") - .overrideConfigKey("quarkus.datasource.password", "sa") - .overrideConfigKey("quarkus.datasource.jdbc.url", - "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); - - @Inject - @FlywayDataSource("users") - Instance flyway; - - @Test - @DisplayName("If the URL is missing for a named datasource, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", - "Datasource 'users' is not configured.", - "To solve this, configure datasource 'users'.", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceStaticInjectionTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceStaticInjectionTest.java deleted file mode 100644 index d9d30ee20b58e..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionConfigUrlMissingNamedDataSourceStaticInjectionTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionConfigUrlMissingNamedDataSourceStaticInjectionTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - // The URL won't be missing if dev services are enabled - .overrideConfigKey("quarkus.devservices.enabled", "false") - // We need at least one build-time property for the datasource, - // otherwise it's considered unconfigured at build time... - .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") - // We need this otherwise the *default* datasource may impact this test - .overrideConfigKey("quarkus.datasource.db-kind", "h2") - .overrideConfigKey("quarkus.datasource.username", "sa") - .overrideConfigKey("quarkus.datasource.password", "sa") - .overrideConfigKey("quarkus.datasource.jdbc.url", - "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); - - @Inject - MyBean myBean; - - @Test - @DisplayName("If the URL is missing for a named datasource, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(() -> myBean.useFlyway()) - .cause() - .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", - "Datasource 'users' is not configured.", - "To solve this, configure datasource 'users'.", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - - @ApplicationScoped - public static class MyBean { - @Inject - @FlywayDataSource("users") - Flyway flyway; - - public void useFlyway() { - flyway.getConfiguration(); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionDisabledTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionDisabledTest.java deleted file mode 100644 index 926eea83f5f8c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionDisabledTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionDisabledTest { - - @Inject - Instance flyway; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("disabled-config.properties", "application.properties")); - - @Test - @DisplayName("No Flyway instance available if disabled") - public void testFlywayConfigInjection() { - assertTrue(flyway.isUnsatisfied()); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionFilesystemResourceTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionFilesystemResourceTest.java deleted file mode 100644 index 3f47ba56287f8..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionFilesystemResourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.h2.jdbc.JdbcSQLSyntaxErrorException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import db.migration.V1_0_1__Update; -import db.migration.V1_0_2__Update; -import io.agroal.api.AgroalDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionFilesystemResourceTest { - - @Inject - Flyway flyway; - - @Inject - AgroalDataSource defaultDataSource; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(V1_0_1__Update.class, V1_0_2__Update.class) - .addAsResource("clean-and-migrate-at-start-with-fs-resource-config.properties", "application.properties")); - - @Test - @DisplayName("Clean and migrate at start correctly") - public void testFlywayConfigInjection() throws SQLException { - - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet executeQuery = stat.executeQuery("select * from fake_existing_tbl")) { - fail("fake_existing_tbl should not exist. Clean was run at start"); - } catch (JdbcSQLSyntaxErrorException e) { - // expected fake_existing_tbl does not exist - } - try (ResultSet countQuery = stat.executeQuery("select count(1) from quarked_flyway")) { - assertTrue(countQuery.first()); - assertEquals(2, - countQuery.getInt(1), - "Table 'quarked_flyway' does not contain the expected number of rows"); - } - } - String currentVersion = flyway.info().current().getVersion().toString(); - assertEquals("1.0.3", currentVersion, "Expected to be 1.0.3 as there is a SQL and two Java migration scripts"); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionInitSqlTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionInitSqlTest.java deleted file mode 100644 index 164058dad5656..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionInitSqlTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import jakarta.inject.Inject; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionInitSqlTest { - // Quarkus built object - @Inject - DataSource datasource; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("init-sql-config.properties", "application.properties")); - - @Test - @DisplayName("Check if initSql is invoked") - public void testFlywayInitSql() throws SQLException { - int var = 0; - try (Connection con = datasource.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT ONE_HUNDRED"); - ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - var = rs.getInt(1); - } - } - assertEquals(100, var, "Init SQL was not executed"); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java deleted file mode 100644 index a17daf98aca41..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionMigrateAtStartDefaultDatasourceConfigActiveFalseTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql")) - .overrideConfigKey("quarkus.datasource.active", "false") - .overrideConfigKey("quarkus.flyway.migrate-at-start", "true"); - - @Inject - Instance flyway; - - @Test - @DisplayName("If the default datasource is deactivated, even if migrate-at-start is enabled, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource '' for Flyway", - "Datasource '' was deactivated through configuration properties.", - "To solve this, avoid accessing this datasource at runtime", - "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'" - + " to 'true' and configure datasource ''", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceUrlMissingTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceUrlMissingTest.java deleted file mode 100644 index d926452bce0e0..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartDefaultDatasourceUrlMissingTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionMigrateAtStartDefaultDatasourceUrlMissingTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql")) - .overrideConfigKey("quarkus.flyway.migrate-at-start", "true") - // The URL won't be missing if dev services are enabled - .overrideConfigKey("quarkus.devservices.enabled", "false"); - - @Inject - Instance flyway; - - @Test - @DisplayName("If there is no config for the default datasource, even if migrate-at-start is enabled, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource '' for Flyway", - "Datasource '' is not configured.", - "To solve this, configure datasource ''.", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDataSourceTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDataSourceTest.java deleted file mode 100644 index d61c8ffd005c6..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDataSourceTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -/** - * Same as {@link FlywayExtensionMigrateAtStartTest} for named datasources. - */ -public class FlywayExtensionMigrateAtStartNamedDataSourceTest { - - @Inject - @FlywayDataSource("users") - Flyway flywayUsers; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("migrate-at-start-config-named-datasource.properties", "application.properties")); - - @Test - @DisplayName("Migrates at start for datasource named 'users' correctly") - public void testFlywayConfigInjection() { - MigrationInfo migrationInfo = flywayUsers.info().current(); - assertNotNull(migrationInfo, "No Flyway migration was executed"); - - String currentVersion = migrationInfo - .getVersion() - .toString(); - // Expected to be 1.0.0 as migration runs at start - assertEquals("1.0.0", currentVersion); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java deleted file mode 100644 index 2f2724e7795dc..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionMigrateAtStartNamedDatasourceConfigActiveFalseTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql")) - .overrideConfigKey("quarkus.datasource.users.active", "false") - .overrideConfigKey("quarkus.flyway.users.migrate-at-start", "true") - // We need at least one build-time property for the datasource, - // otherwise it's considered unconfigured at build time... - .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") - // We need this otherwise the *default* datasource may impact this test - .overrideConfigKey("quarkus.datasource.db-kind", "h2") - .overrideConfigKey("quarkus.datasource.username", "sa") - .overrideConfigKey("quarkus.datasource.password", "sa") - .overrideConfigKey("quarkus.datasource.jdbc.url", - "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); - - @Inject - @FlywayDataSource("users") - Instance flyway; - - @Test - @DisplayName("If a named datasource is deactivated, even if migrate-at-start is enabled, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", - "Datasource 'users' was deactivated through configuration properties.", - "To solve this, avoid accessing this datasource at runtime", - "Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'" - + " to 'true' and configure datasource 'users'", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigUrlMissingTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigUrlMissingTest.java deleted file mode 100644 index ecd58cb725583..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartNamedDatasourceConfigUrlMissingTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import jakarta.enterprise.inject.CreationException; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionMigrateAtStartNamedDatasourceConfigUrlMissingTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql")) - .overrideConfigKey("quarkus.flyway.users.migrate-at-start", "true") - // The URL won't be missing if dev services are enabled - .overrideConfigKey("quarkus.devservices.enabled", "false") - // We need at least one build-time property for the datasource, - // otherwise it's considered unconfigured at build time... - .overrideConfigKey("quarkus.datasource.users.db-kind", "h2") - // We need this otherwise the *default* datasource may impact this test - .overrideConfigKey("quarkus.datasource.db-kind", "h2") - .overrideConfigKey("quarkus.datasource.username", "sa") - .overrideConfigKey("quarkus.datasource.password", "sa") - .overrideConfigKey("quarkus.datasource.jdbc.url", - "jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1"); - - @Inject - @FlywayDataSource("users") - Instance flyway; - - @Test - @DisplayName("If there is no config for a named datasource, even if migrate-at-start is enabled, the application should boot, but Flyway should be deactivated for that datasource") - public void testBootSucceedsButFlywayDeactivated() { - assertThatThrownBy(flyway::get) - .isInstanceOf(CreationException.class) - .cause() - .hasMessageContainingAll("Unable to find datasource 'users' for Flyway", - "Datasource 'users' is not configured.", - "To solve this, configure datasource 'users'.", - "Refer to https://quarkus.io/guides/datasource for guidance."); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartSubfolderTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartSubfolderTest.java deleted file mode 100644 index 7877dabb10415..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartSubfolderTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionMigrateAtStartSubfolderTest { - // Quarkus built object - @Inject - Flyway flyway; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration-subfolder/subfolder/V1.0.0__Quarkus.sql") - .addAsResource("migrate-at-start-subfolder-config.properties", "application.properties")); - - @Test - @DisplayName("Migrates at start correctly") - public void testFlywayConfigInjection() { - MigrationInfo migrationInfo = flyway.info().current(); - assertNotNull(migrationInfo, "No Flyway migration was executed"); - - String currentVersion = migrationInfo - .getVersion() - .toString(); - // Expected to be 1.0.0 as migration runs at start - assertEquals("1.0.0", currentVersion); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartTest.java deleted file mode 100644 index 7458667c4a102..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionMigrateAtStartTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import jakarta.inject.Inject; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.MigrationInfo; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionMigrateAtStartTest { - // Quarkus built object - @Inject - Flyway flyway; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("migrate-at-start-config.properties", "application.properties")); - - @Test - @DisplayName("Migrates at start correctly") - public void testFlywayConfigInjection() { - MigrationInfo migrationInfo = flyway.info().current(); - assertNotNull(migrationInfo, "No Flyway migration was executed"); - - String currentVersion = migrationInfo - .getVersion() - .toString(); - - assertEquals("1.0.0", currentVersion); - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionRepairAtStartTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionRepairAtStartTest.java deleted file mode 100644 index f0f3e76517859..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionRepairAtStartTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; - -import java.util.concurrent.TimeUnit; - -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; - -import org.flywaydb.core.Flyway; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.runtime.util.ExceptionUtil; -import io.quarkus.test.QuarkusDevModeTest; -import io.restassured.RestAssured; - -public class FlywayExtensionRepairAtStartTest { - - @RegisterExtension - static final QuarkusDevModeTest config = new QuarkusDevModeTest() - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addClass(FlywayResource.class) - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("repair-at-start-config.properties", "application.properties")) - .setLogRecordPredicate(r -> true) - .setAllowFailedStart(true); - - @Test - @DisplayName("Repair at start works correctly") - public void testRepairUsingDevMode() { - assertThat(RestAssured.get("/flyway/current-version").then().statusCode(200).extract().asString()).isEqualTo("1.0.0"); - - config.clearLogRecords(); - config.modifyResourceFile("db/migration/V1.0.0__Quarkus.sql", s -> s + "\nNONSENSE STATEMENT CHANGING CHECKSUM;"); - config.modifyResourceFile("application.properties", s -> s + "\nquarkus.flyway.validate-on-migrate=true"); - - // trigger application restart - RestAssured.get("/"); - - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { - assertThat(config.getLogRecords()).anySatisfy(r -> { - assertThat(r.getMessage()).contains("Failed to start application"); - assertThat(ExceptionUtil.getRootCause(r.getThrown()).getMessage()) - .contains("Migration checksum mismatch for migration version 1.0.0"); - }); - RestAssured.get("/flyway/current-version").then().statusCode(500); - }); - - config.clearLogRecords(); - config.modifyResourceFile("application.properties", s -> s + "\nquarkus.flyway.repair-at-start=true"); - - // trigger application restart - RestAssured.get("/"); - - await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { - assertThat(config.getLogRecords()).anySatisfy( - r -> assertThat(r.getMessage()).contains("Successfully repaired schema history table")); - assertThat(RestAssured.get("/flyway/current-version").then().statusCode(200).extract().asString()) - .isEqualTo("1.0.0"); - }); - } - - @Path("flyway") - public static class FlywayResource { - @Inject - Flyway flyway; - - @Path("current-version") - @GET - public String currentVersion() { - return flyway.info().current().getVersion().toString(); - } - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionValidateAtStartTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionValidateAtStartTest.java deleted file mode 100644 index bd1b3df360cf0..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionValidateAtStartTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import org.flywaydb.core.api.exception.FlywayValidateException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionValidateAtStartTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("validate-at-start-config.properties", "application.properties")) - .setExpectedException(FlywayValidateException.class); - - @Test - public void shouldNeverBeCalled() { - - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithCustomizerTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithCustomizerTest.java deleted file mode 100644 index 8b13adf3a99f2..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithCustomizerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -import org.flywaydb.core.api.configuration.FluentConfiguration; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.agroal.api.AgroalDataSource; -import io.quarkus.flyway.FlywayConfigurationCustomizer; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionWithCustomizerTest { - - @Inject - AgroalDataSource defaultDataSource; - - static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer - .withDbName("quarkus-customizer") - .withPort(11303) - .withInitSqlFile("src/test/resources/callback-init-data.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(customizer::startH2) - .setAfterAllCustomizer(customizer::stopH2) - .withApplicationRoot((jar) -> jar - .addClasses(FlywayH2TestCustomizer.class, - AddCallbacksCustomizer.class, - FlywayExtensionCallback.class, FlywayExtensionCallback2.class, FlywayExtensionCDICallback.class) - .addAsResource("db/migration/V1.0.3__Quarkus_Callback.sql") - .addAsResource("config-for-default-datasource-with-customizer-config.properties", - "application.properties")); - - @Test - public void testCustomizer() throws SQLException { - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet executeQuery = stat.executeQuery("select COUNT(name) from quarked_callback")) { - assertTrue(executeQuery.next(), "Table exists but it is empty"); - int count = executeQuery.getInt(1); - // Expect one row for each callback invoked by Flyway - int expected = FlywayExtensionCallback.DEFAULT_EVENTS.size() + FlywayExtensionCallback2.DEFAULT_EVENTS.size(); - assertEquals(expected, count); - } - } - } - - @Singleton - public static class AddCallbacksCustomizer implements FlywayConfigurationCustomizer { - - @Override - public void customize(FluentConfiguration configuration) { - configuration.callbacks(new FlywayExtensionCallback(), new FlywayExtensionCallback2(), - new FlywayExtensionCDICallback()); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTest.java deleted file mode 100644 index 3b6d92127bb42..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static io.restassured.RestAssured.get; -import static org.hamcrest.Matchers.is; - -import java.sql.SQLException; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import db.migration.V1_0_1__Update; -import db.migration.V1_0_2__Update; -import io.quarkus.test.QuarkusDevModeTest; - -public class FlywayExtensionWithJavaMigrationDevModeTest { - - @RegisterExtension - static final QuarkusDevModeTest config = new QuarkusDevModeTest() - .withApplicationRoot((jar) -> jar - .addClasses(V1_0_1__Update.class, V1_0_2__Update.class, - FlywayExtensionWithJavaMigrationDevModeTestEndpoint.class) - .addAsResource("db/migration/V1.0.0__Quarkus.sql") - .addAsResource("clean-and-migrate-at-start-config.properties", "application.properties")); - - @Test - public void test() throws SQLException { - get("/fly") - .then() - .statusCode(200) - .body(is("2/1.0.2")); - - config.modifySourceFile(FlywayExtensionWithJavaMigrationDevModeTestEndpoint.class, s -> s.replace("/fly", "/flyway")); - - get("/flyway") - .then() - .statusCode(200) - .body(is("2/1.0.2")); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTestEndpoint.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTestEndpoint.java deleted file mode 100644 index 35c5984cbab2c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithJavaMigrationDevModeTestEndpoint.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; - -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; - -import org.flywaydb.core.Flyway; - -import io.agroal.api.AgroalDataSource; - -@Path("/fly") -public class FlywayExtensionWithJavaMigrationDevModeTestEndpoint { - - @Inject - AgroalDataSource defaultDataSource; - - @Inject - Flyway flyway; - - @GET - public String result() throws Exception { - int count = 0; - try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet countQuery = stat.executeQuery("select count(1) from quarked_flyway")) { - countQuery.first(); - count = countQuery.getInt(1); - } - } - String currentVersion = flyway.info().current().getVersion().toString(); - - return count + "/" + currentVersion; - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithMultipleDatasourcesAndCustomizersTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithMultipleDatasourcesAndCustomizersTest.java deleted file mode 100644 index a261dbaab3d24..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayExtensionWithMultipleDatasourcesAndCustomizersTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.inject.Singleton; - -import org.flywaydb.core.api.configuration.FluentConfiguration; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.agroal.api.AgroalDataSource; -import io.quarkus.flyway.FlywayConfigurationCustomizer; -import io.quarkus.flyway.FlywayDataSource; -import io.quarkus.test.QuarkusUnitTest; - -public class FlywayExtensionWithMultipleDatasourcesAndCustomizersTest { - - @Inject - AgroalDataSource defaultDataSource; - - @Inject - @Named("users") - AgroalDataSource usersDataSource; - - @Inject - @Named("inventory") - AgroalDataSource inventoryDataSource; - - static final FlywayH2TestCustomizer h2ForDefault = FlywayH2TestCustomizer - .withDbName("quarkus-default-customizer") - .withPort(11303) - .withInitSqlFile("src/test/resources/callback-init-data.sql"); - - static final FlywayH2TestCustomizer h2ForUsers = FlywayH2TestCustomizer - .withDbName("quarkus-users-customizer") - .withPort(11304) - .withInitSqlFile("src/test/resources/callback-init-data.sql"); - - static final FlywayH2TestCustomizer h2ForInventory = FlywayH2TestCustomizer - .withDbName("quarkus-inventory-customizer") - .withPort(11305) - .withInitSqlFile("src/test/resources/callback-init-data.sql"); - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setBeforeAllCustomizer(new Runnable() { - @Override - public void run() { - h2ForDefault.startH2(); - h2ForUsers.startH2(); - h2ForInventory.startH2(); - } - }) - .setAfterAllCustomizer(new Runnable() { - @Override - public void run() { - h2ForDefault.stopH2(); - h2ForUsers.stopH2(); - h2ForInventory.stopH2(); - } - }) - .withApplicationRoot((jar) -> jar - .addClasses(FlywayH2TestCustomizer.class, - AddCallbacksCustomizerForDefaultDS.class, - FlywayExtensionCallback.class, FlywayExtensionCallback2.class, FlywayExtensionCDICallback.class) - .addAsResource("db/migration/V1.0.3__Quarkus_Callback.sql") - .addAsResource("config-for-multiple-datasource-with-customizers-config.properties", - "application.properties")); - - @Test - public void testCustomizers() throws SQLException { - assertEventCount(defaultDataSource, FlywayExtensionCallback.DEFAULT_EVENTS.size()); - assertEventCount(usersDataSource, FlywayExtensionCallback2.DEFAULT_EVENTS.size()); - assertEventCount(inventoryDataSource, 0); - } - - private void assertEventCount(AgroalDataSource dataSource, int expectedEventCount) throws SQLException { - try (Connection connection = dataSource.getConnection(); Statement stat = connection.createStatement()) { - try (ResultSet executeQuery = stat.executeQuery("select COUNT(name) from quarked_callback")) { - assertTrue(executeQuery.next(), "Table exists but it is empty"); - int count = executeQuery.getInt(1); - assertEquals(expectedEventCount, count); - } - } - } - - @Singleton - public static class AddCallbacksCustomizerForDefaultDS implements FlywayConfigurationCustomizer { - - @Override - public void customize(FluentConfiguration configuration) { - configuration.callbacks(new FlywayExtensionCallback()); - } - } - - @Singleton - @FlywayDataSource("users") - public static class AddCallbacksCustomizerForUsersDS implements FlywayConfigurationCustomizer { - - @Override - public void customize(FluentConfiguration configuration) { - configuration.callbacks(new FlywayExtensionCallback2()); - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayH2TestCustomizer.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayH2TestCustomizer.java deleted file mode 100644 index 2b137bbc769e6..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayH2TestCustomizer.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static java.util.Objects.requireNonNull; - -import java.nio.charset.Charset; -import java.sql.SQLException; -import java.util.concurrent.ThreadLocalRandom; - -import org.h2.tools.RunScript; -import org.h2.tools.Server; - -public class FlywayH2TestCustomizer { - private String initSqlFile; - private String dbName; - private int port = ThreadLocalRandom.current().nextInt(49152, 65535); - private Server tcpServer; - - protected FlywayH2TestCustomizer() { - } - - private FlywayH2TestCustomizer(String dbName) { - this.dbName = dbName; - } - - public static FlywayH2TestCustomizer withDbName(String dbName) { - return new FlywayH2TestCustomizer(dbName); - } - - public FlywayH2TestCustomizer withPort(int port) { - this.port = port; - return this; - } - - public FlywayH2TestCustomizer withInitSqlFile(String initSqlFile) { - this.initSqlFile = initSqlFile; - return this; - } - - void startH2() { - try { - tcpServer = Server.createTcpServer("-tcpPort", String.valueOf(port), "-ifNotExists"); - tcpServer.start(); - System.out.println("[INFO] Custom H2 database started in TCP server mode; server status: " + tcpServer.getStatus()); - if (initSqlFile != null) { - executeInitSQL(); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - void executeInitSQL() { - requireNonNull(dbName, "Flyway-H2: Default db for init-sql must be specified!"); - requireNonNull(initSqlFile, "Flyway-H2: init-sql must be specified!"); - final String url = buildDbURL(); - try { - System.out.println("[INFO] Custom H2 Initializing DB: " + url); - RunScript.execute( - url, - "sa", - "sa", - initSqlFile, - Charset.defaultCharset(), - false); - } catch (SQLException exception) { - throw new RuntimeException(exception); - } - } - - public String buildDbURL() { - return "jdbc:h2:tcp://localhost:" + port + "/mem:" + dbName + ";DB_CLOSE_DELAY=-1"; - } - - public void stopH2() { - if (tcpServer != null) { - tcpServer.stop(); - System.out.println("[INFO] Custom H2 database was shut down; server status: " + tcpServer.getStatus()); - tcpServer = null; - } - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayMultiDataSourcesDevModeTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayMultiDataSourcesDevModeTest.java deleted file mode 100644 index fd54e05d85fe5..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/FlywayMultiDataSourcesDevModeTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import static org.hamcrest.CoreMatchers.containsString; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusDevModeTest; -import io.restassured.RestAssured; - -// see https://github.com/quarkusio/quarkus/issues/9415 -public class FlywayMultiDataSourcesDevModeTest { - - @RegisterExtension - static final QuarkusDevModeTest config = new QuarkusDevModeTest() - .withApplicationRoot((jar) -> jar - .addClasses(MultiDataSourcesDevModeEndpoint.class, FlywayExtensionCallback.class) - .addAsResource("config-for-multiple-datasources.properties", "application.properties")); - - @Test - public void testProperConfigApplied() { - RestAssured.get("/fly").then() - .statusCode(200) - .body(containsString("db/location1,db/location2")); - - RestAssured.get("/fly?name=users").then() - .statusCode(200) - .body(containsString("db/users/location1,db/users/location2")); - - RestAssured.get("/fly?name=inventory").then() - .statusCode(200) - .body(containsString("db/inventory/location1,db/inventory/location")); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/Fruit.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/Fruit.java deleted file mode 100644 index 13986afe6035c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/Fruit.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; - -@Entity -public class Fruit { - @Id - @GeneratedValue - private Integer id; - - @Column(length = 40, unique = true) - private String name; - - public Fruit() { - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MigrateAtStartMultiTenancyTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MigrateAtStartMultiTenancyTest.java new file mode 100644 index 0000000000000..56d40b517649b --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MigrateAtStartMultiTenancyTest.java @@ -0,0 +1,117 @@ +package io.quarkus.flyway.multitenant.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.MigrationInfo; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.arc.Unremovable; +import io.quarkus.flyway.FlywayTenantSupport; +import io.quarkus.flyway.multitenant.runtime.FlywayPersistenceUnit; +import io.quarkus.hibernate.orm.PersistenceUnitExtension; +import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver; +import io.quarkus.test.QuarkusUnitTest; + +public class MigrateAtStartMultiTenancyTest { + + @Inject + @FlywayPersistenceUnit(tenantId = "tenant1") + Flyway tenant1; + + @Inject + @FlywayPersistenceUnit(tenantId = "tenant2") + Flyway tenant2; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Fruit.class, TestTenantResolver.class, TenantToInitialize.class) + .addAsResource("db/migration/V1.0.0__Quarkus.sql") + .addAsResource("migrate-at-start-multitenancy.properties", "application.properties")); + + @Test + public void testMigrateAtStart() { + MigrationInfo migrationInfo = tenant1.info().current(); + assertNotNull(migrationInfo, "No Flyway migration was executed on tenant 1"); + + String currentVersion = migrationInfo + .getVersion() + .toString(); + + assertEquals("1.0.0", currentVersion); + + migrationInfo = tenant2.info().current(); + assertNotNull(migrationInfo, "No Flyway migration was executed on tenant 2"); + + currentVersion = migrationInfo + .getVersion() + .toString(); + + assertEquals("1.0.0", currentVersion); + } + + @Entity + public static class Fruit { + @Id + @GeneratedValue + private Integer id; + + @Column(length = 40, unique = true) + private String name; + + public Fruit() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @PersistenceUnitExtension() + public static class TestTenantResolver implements TenantResolver { + + @Override + public String getDefaultTenantId() { + return "tenant1"; + } + + @Override + public String resolveTenantId() { + return "tenant2"; + } + } + + @ApplicationScoped + @Unremovable + public static class TenantToInitialize implements FlywayTenantSupport { + + @Override + public List getTenantsToInitialize() { + return List.of("tenant1", "tenant2"); + } + } +} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MultiDataSourcesDevModeEndpoint.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MultiDataSourcesDevModeEndpoint.java deleted file mode 100644 index 08c42193fbbb2..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/MultiDataSourcesDevModeEndpoint.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.quarkus.flyway.multitenant.test; - -import java.util.Arrays; -import java.util.stream.Collectors; - -import jakarta.inject.Inject; -import jakarta.ws.rs.DefaultValue; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.Location; -import org.flywaydb.core.api.configuration.Configuration; - -import io.quarkus.flyway.FlywayDataSource; - -@Path("/fly") -public class MultiDataSourcesDevModeEndpoint { - - @Inject - Flyway flywayDefault; - - @Inject - @FlywayDataSource("users") - Flyway flywayUsers; - - @Inject - @FlywayDataSource("inventory") - Flyway flywayInventory; - - @GET - @Produces("text/plain") - public String locations(@QueryParam("name") @DefaultValue("default") String name) { - Configuration configuration; - if ("default".equals(name)) { - configuration = flywayDefault.getConfiguration(); - } else if ("users".equals(name)) { - configuration = flywayUsers.getConfiguration(); - } else if ("inventory".equals(name)) { - configuration = flywayInventory.getConfiguration(); - } else { - throw new RuntimeException("Flyway " + name + " not found"); - } - - return Arrays.stream(configuration.getLocations()).map(Location::getPath).collect(Collectors.joining(",")); - } - -} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NamedPersistenceUnitTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NamedPersistenceUnitTest.java new file mode 100644 index 0000000000000..80d82fec4ddc7 --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NamedPersistenceUnitTest.java @@ -0,0 +1,112 @@ +package io.quarkus.flyway.multitenant.test; + +import jakarta.inject.Inject; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.flyway.multitenant.runtime.FlywayPersistenceUnit; +import io.quarkus.flyway.runtime.FlywayContainer; +import io.quarkus.hibernate.orm.PersistenceUnitExtension; +import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver; +import io.quarkus.test.QuarkusUnitTest; + +public class NamedPersistenceUnitTest { + + @Inject + @FlywayPersistenceUnit("named") + FlywayContainer container; + + @Inject + @FlywayPersistenceUnit(value = "named", tenantId = "tenant2") + Flyway tenant2; + + @Inject + @FlywayPersistenceUnit("named") + Flyway flyway; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Fruit.class, TestTenantResolver.class) + .addAsResource("named-peristence-unit.properties", "application.properties")); + + @Test + public void testContainer() { + Assertions.assertTrue(container.isMultiTenancyEnabled()); + } + + @Test + public void testGettingTenantScopedFlyway() { + Flyway tenant1 = container.getFlyway("tenant1"); + Assertions.assertNotNull(tenant1); + Assertions.assertEquals("tenant1", tenant1.getConfiguration().getDefaultSchema()); + } + + @Test + public void testInjectingTenantScopedFlyway() { + Assertions.assertNotNull(tenant2); + Assertions.assertEquals("tenant2", tenant2.getConfiguration().getDefaultSchema()); + } + + @Test + public void testGettingGlobalFlyway() { + Flyway flyway = container.getFlyway(); + Assertions.assertNotNull(flyway); + } + + @Test + public void testInjectingGlobalFlyway() { + Assertions.assertNotNull(flyway); + Assertions.assertNull(flyway.getConfiguration().getDefaultSchema()); + } + + @Entity + public static class Fruit { + @Id + @GeneratedValue + private Integer id; + + @Column(length = 40, unique = true) + private String name; + + public Fruit() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @PersistenceUnitExtension("named") + public static class TestTenantResolver implements TenantResolver { + + @Override + public String getDefaultTenantId() { + return "defaultTenantId"; + } + + @Override + public String resolveTenantId() { + return "theTenantId"; + } + } +} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NoMultiTenancyTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NoMultiTenancyTest.java new file mode 100644 index 0000000000000..fd77f1dfbd2ea --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/NoMultiTenancyTest.java @@ -0,0 +1,93 @@ +package io.quarkus.flyway.multitenant.test; + +import jakarta.enterprise.inject.spi.CDI; +import jakarta.inject.Inject; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.flyway.multitenant.runtime.FlywayPersistenceUnit; +import io.quarkus.flyway.multitenant.runtime.FlywayPersistenceUnit.FlywayPersistenceUnitLiteral; +import io.quarkus.flyway.runtime.FlywayContainer; +import io.quarkus.test.QuarkusUnitTest; + +public class NoMultiTenancyTest { + + @Inject + @FlywayPersistenceUnit() + FlywayContainer container; + + @Inject + @FlywayPersistenceUnit() + Flyway flyway; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Fruit.class) + .addAsResource("no-multitenancy.properties", "application.properties")); + + @Test + public void testContainer() { + Assertions.assertFalse(container.isMultiTenancyEnabled()); + } + + @Test + public void testInjectingGlobalFlyway() { + Assertions.assertNotNull(flyway); + Assertions.assertNull(flyway.getConfiguration().getDefaultSchema()); + } + + @Test + public void testInjectingTenantScopedFlywayIsFailing() { + Assertions.assertThrows(RuntimeException.class, + () -> CDI.current().select(Flyway.class, FlywayPersistenceUnitLiteral.of("tenant2")).get()); + + } + + @Test + public void testGettingTenantScopedFlywayIsFailing() { + Assertions.assertThrows(RuntimeException.class, () -> container.getFlyway("tenant1")); + } + + @Test + public void testGettingGlobalFlyway() { + Flyway flyway = container.getFlyway(); + Assertions.assertNotNull(flyway); + } + + @Entity + public static class Fruit { + @Id + @GeneratedValue + private Integer id; + + @Column(length = 40, unique = true) + private String name; + + public Fruit() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/SchemaMultiTenancyTest.java b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/SchemaMultiTenancyTest.java new file mode 100644 index 0000000000000..f9678496a0721 --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/java/io/quarkus/flyway/multitenant/test/SchemaMultiTenancyTest.java @@ -0,0 +1,112 @@ +package io.quarkus.flyway.multitenant.test; + +import jakarta.inject.Inject; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.flyway.multitenant.runtime.FlywayPersistenceUnit; +import io.quarkus.flyway.runtime.FlywayContainer; +import io.quarkus.hibernate.orm.PersistenceUnitExtension; +import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver; +import io.quarkus.test.QuarkusUnitTest; + +public class SchemaMultiTenancyTest { + + @Inject + @FlywayPersistenceUnit() + FlywayContainer container; + + @Inject + @FlywayPersistenceUnit(tenantId = "tenant2") + Flyway tenant2; + + @Inject + @FlywayPersistenceUnit() + Flyway flyway; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Fruit.class, TestTenantResolver.class) + .addAsResource("schema-multitenancy.properties", "application.properties")); + + @Test + public void testContainer() { + Assertions.assertTrue(container.isMultiTenancyEnabled()); + } + + @Test + public void testGettingTenantScopedFlyway() { + Flyway tenant1 = container.getFlyway("tenant1"); + Assertions.assertNotNull(tenant1); + Assertions.assertEquals("tenant1", tenant1.getConfiguration().getDefaultSchema()); + } + + @Test + public void testInjectingTenantScopedFlyway() { + Assertions.assertNotNull(tenant2); + Assertions.assertEquals("tenant2", tenant2.getConfiguration().getDefaultSchema()); + } + + @Test + public void testGettingGlobalFlyway() { + Flyway flyway = container.getFlyway(); + Assertions.assertNotNull(flyway); + } + + @Test + public void testInjectingGlobalFlyway() { + Assertions.assertNotNull(flyway); + Assertions.assertNull(flyway.getConfiguration().getDefaultSchema()); + } + + @Entity + public static class Fruit { + @Id + @GeneratedValue + private Integer id; + + @Column(length = 40, unique = true) + private String name; + + public Fruit() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @PersistenceUnitExtension() + public static class TestTenantResolver implements TenantResolver { + + @Override + public String getDefaultTenantId() { + return "defaultTenantId"; + } + + @Override + public String resolveTenantId() { + return "theTenantId"; + } + } +} diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties deleted file mode 100644 index 23d6fbbc2303c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties +++ /dev/null @@ -1,8 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11309/mem:quarkus-baseline-at-start-existing-schema-history;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.baseline-at-start=true -quarkus.flyway.baseline-version=1.0.1 \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasource.properties b/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasource.properties deleted file mode 100644 index bdae3e948bf8c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasource.properties +++ /dev/null @@ -1,10 +0,0 @@ -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=sa -quarkus.datasource.users.password=sa -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost:11302/mem:quarkus-flyway-baseline-on-named-ds -# Flyway config properties -quarkus.flyway.users.migrate-at-start=true -quarkus.flyway.users.table=test_flyway_history -quarkus.flyway.users.baseline-on-migrate=true -quarkus.flyway.users.baseline-version=0.0.1 -quarkus.flyway.users.baseline-description=Initial description for test diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties b/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties deleted file mode 100644 index d816d7b5a8451..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties +++ /dev/null @@ -1,24 +0,0 @@ -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=sa -quarkus.datasource.users.password=sa -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost:11302/mem:quarkus-flyway-baseline-on-named-ds-users - -# Flyway config properties -quarkus.flyway.users.migrate-at-start=true -quarkus.flyway.users.table=test_flyway_history -quarkus.flyway.users.baseline-on-migrate=true -quarkus.flyway.users.baseline-version=0.0.1 -quarkus.flyway.users.baseline-description=Initial description for test - -quarkus.datasource.laptops.db-kind=h2 -quarkus.datasource.laptops.username=sa -quarkus.datasource.laptops.password=sa -quarkus.datasource.laptops.jdbc.url=jdbc:h2:tcp://localhost:11302/mem:quarkus-flyway-baseline-on-named-ds-laptops - -# Flyway config properties -quarkus.flyway.laptops.active=false -quarkus.flyway.laptops.migrate-at-start=true -quarkus.flyway.laptops.table=test_flyway_history -quarkus.flyway.laptops.baseline-on-migrate=true -quarkus.flyway.laptops.baseline-version=0.0.1 -quarkus.flyway.laptops.baseline-description=Initial description for test diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate.properties b/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate.properties deleted file mode 100644 index db84abca3e79c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-on-migrate.properties +++ /dev/null @@ -1,10 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11301/mem:quarkus-flyway-baseline-on-migrate -# Flyway config properties -quarkus.flyway.migrate-at-start=true -quarkus.flyway.table=test_flyway_history -quarkus.flyway.baseline-on-migrate=true -quarkus.flyway.baseline-version=0.0.1 -quarkus.flyway.baseline-description=Initial description for test diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/callback-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/callback-config.properties deleted file mode 100644 index f5d91dc0e7c56..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/callback-config.properties +++ /dev/null @@ -1,10 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11303/mem:quarkus-flyway-callback;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.migrate-at-start=true -quarkus.flyway.baseline-on-migrate=true -quarkus.flyway.baseline-version=0.0.1 -quarkus.flyway.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback,io.quarkus.flyway.test.FlywayExtensionCallback2,io.quarkus.flyway.test.FlywayExtensionCDICallback diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/callback-init-data.sql b/extensions/flyway-multitenant/deployment/src/test/resources/callback-init-data.sql deleted file mode 100644 index 0adea0251a6cc..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/callback-init-data.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE quarked_callback -( - name VARCHAR(120) -); diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-config.properties deleted file mode 100644 index 26c07c53ca008..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-config.properties +++ /dev/null @@ -1,13 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-flyway;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.clean-at-start=true -quarkus.flyway.migrate-at-start=true -quarkus.flyway.table=test_flyway_history -quarkus.flyway.baseline-on-migrate=false -quarkus.flyway.baseline-version=0.0.1 -quarkus.flyway.baseline-description=Initial description for test -quarkus.flyway.users.locations=db/migration \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-with-fs-resource-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-with-fs-resource-config.properties deleted file mode 100644 index 65afb9365aa52..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/clean-and-migrate-at-start-with-fs-resource-config.properties +++ /dev/null @@ -1,13 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-flyway;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.clean-at-start=true -quarkus.flyway.migrate-at-start=true -quarkus.flyway.table=test_flyway_history -quarkus.flyway.baseline-on-migrate=false -quarkus.flyway.baseline-version=0.0.1 -quarkus.flyway.baseline-description=Initial description for test -quarkus.flyway.locations=filesystem:src/test/resources/db/migration,classpath:db/migration diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/clean-at-start-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/clean-at-start-config.properties deleted file mode 100644 index 35ab099fc98f0..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/clean-at-start-config.properties +++ /dev/null @@ -1,14 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-clean-at-start;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS TEST - -# Flyway config properties -quarkus.flyway.clean-at-start=true -quarkus.flyway.migrate-at-start=false -quarkus.flyway.table=test_flyway_history -quarkus.flyway.default-schema=PUBLIC -quarkus.flyway.schemas=TEST,PUBLIC -quarkus.flyway.baseline-on-migrate=false -quarkus.flyway.baseline-version=0.0.1 -quarkus.flyway.baseline-description=Initial description for test diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-empty.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-empty.properties deleted file mode 100644 index 7484177fc8b23..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-empty.properties +++ /dev/null @@ -1 +0,0 @@ -quarkus.datasource.devservices.enabled=false \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-with-customizer-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-with-customizer-config.properties deleted file mode 100644 index c7551b0da4e5c..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-with-customizer-config.properties +++ /dev/null @@ -1,9 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11303/mem:quarkus-customizer;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.migrate-at-start=true -quarkus.flyway.baseline-on-migrate=true -quarkus.flyway.baseline-version=0.0.1 diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-without-flyway.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-without-flyway.properties deleted file mode 100644 index e56388ea03880..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource-without-flyway.properties +++ /dev/null @@ -1,4 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test_quarkus;DB_CLOSE_DELAY=-1 diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource.properties deleted file mode 100644 index 3c8e026ab10f9..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-default-datasource.properties +++ /dev/null @@ -1,19 +0,0 @@ -#default datasource -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test_quarkus;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.connect-retries=10 -quarkus.flyway.connect-retries-interval=100ms -quarkus.flyway.schemas=TEST_SCHEMA -quarkus.flyway.table=flyway_quarkus_history -quarkus.flyway.locations=db/location1,db/location2 -quarkus.flyway.sql-migration-prefix=X -quarkus.flyway.repeatable-sql-migration-prefix=K -quarkus.flyway.migrate-at-start=false -quarkus.flyway.baseline-on-migrate=true -quarkus.flyway.baseline-version=2.0.1 -quarkus.flyway.baseline-description=Initial description -quarkus.flyway.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback,io.quarkus.flyway.test.FlywayExtensionCallback2 diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-missing-named-datasource.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-missing-named-datasource.properties deleted file mode 100644 index 86e971af9d39e..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-missing-named-datasource.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Datasource for "inventory" -quarkus.datasource.inventory.db-kind=h2 -quarkus.datasource.inventory.username=username2 -quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localhost/mem:inventory -quarkus.datasource.inventory.jdbc.max-size=12 -quarkus.datasource.inventory.jdbc.transactions=xa - -# Flyway configuration for missing "users" datasource -quarkus.flyway.users.connect-retries=11 -quarkus.flyway.connect-retries-interval=1 -quarkus.flyway.users.schemas=USERS_TEST_SCHEMA -quarkus.flyway.users.table=users_flyway_quarkus_history -quarkus.flyway.users.locations=db/users/location1,db/users/location2 -quarkus.flyway.users.sql-migration-prefix=U -quarkus.flyway.users.repeatable-sql-migration-prefix=S -quarkus.flyway.users.migrate-at-start=false -quarkus.flyway.users.baseline-on-migrate=true -quarkus.flyway.users.baseline-version=2.0.1 -quarkus.flyway.users.baseline-description=Users initial description \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasource-with-customizers-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasource-with-customizers-config.properties deleted file mode 100644 index f03c201799ab5..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasource-with-customizers-config.properties +++ /dev/null @@ -1,24 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11303/mem:quarkus-default-customizer;DB_CLOSE_DELAY=-1 - -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=sa -quarkus.datasource.users.password=sa -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost:11304/mem:quarkus-users-customizer;DB_CLOSE_DELAY=-1 - -quarkus.datasource.inventory.db-kind=h2 -quarkus.datasource.inventory.username=sa -quarkus.datasource.inventory.password=sa -quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localhost:11305/mem:quarkus-inventory-customizer;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.migrate-at-start=true -quarkus.flyway.baseline-on-migrate=true - -quarkus.flyway.users.migrate-at-start=true -quarkus.flyway.users.baseline-on-migrate=true - -quarkus.flyway.inventory.migrate-at-start=true -quarkus.flyway.inventory.baseline-on-migrate=true diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources-without-default.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources-without-default.properties deleted file mode 100644 index bc58f668ce8f6..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources-without-default.properties +++ /dev/null @@ -1,41 +0,0 @@ -# Datasource for "users" -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=username1 -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/mem:users -quarkus.datasource.users.jdbc.max-size=11 - -# Datasource for "inventory" -quarkus.datasource.inventory.db-kind=h2 -quarkus.datasource.inventory.username=username2 -quarkus.datasource.inventory.jdbc.driver=org.h2.jdbcx.JdbcDataSource -quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localhost/mem:inventory -quarkus.datasource.inventory.jdbc.max-size=12 -quarkus.datasource.inventory.jdbc.transactions=xa - -# Flyway configuration for "users" datasource -quarkus.flyway.users.connect-retries=11 -quarkus.flyway.users.connect-retries-interval=2s -quarkus.flyway.users.schemas=USERS_TEST_SCHEMA -quarkus.flyway.users.table=users_flyway_quarkus_history -quarkus.flyway.users.locations=db/users/location1,db/users/location2 -quarkus.flyway.users.sql-migration-prefix=U -quarkus.flyway.users.repeatable-sql-migration-prefix=S -quarkus.flyway.users.migrate-at-start=false -quarkus.flyway.users.baseline-on-migrate=true -quarkus.flyway.users.baseline-version=2.0.1 -quarkus.flyway.users.baseline-description=Users initial description -quarkus.flyway.users.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback - -# Flyway configuration for "inventory" datasource -quarkus.flyway.inventory.connect-retries=12 -quarkus.flyway.inventory.connect-retries-interval=2s -quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA -quarkus.flyway.inventory.table=inventory_flyway_quarkus_history -quarkus.flyway.inventory.locations=db/inventory/location1,db/inventory/location2 -quarkus.flyway.inventory.sql-migration-prefix=I -quarkus.flyway.inventory.repeatable-sql-migration-prefix=N -quarkus.flyway.inventory.migrate-at-start=false -quarkus.flyway.inventory.baseline-on-migrate=true -quarkus.flyway.inventory.baseline-version=3.0.1 -quarkus.flyway.inventory.baseline-description=Inventory initial description -quarkus.flyway.inventory.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources.properties deleted file mode 100644 index 6edbdc877e858..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-multiple-datasources.properties +++ /dev/null @@ -1,61 +0,0 @@ -# Datasource default -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test_quarkus;DB_CLOSE_DELAY=-1 - -# Datasource for "users" -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=username1 -quarkus.datasource.users.jdbc.driver=org.h2.Driver -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/mem:users -quarkus.datasource.users.jdbc.max-size=11 - -# Datasource for "inventory" -quarkus.datasource.inventory.db-kind=h2 -quarkus.datasource.inventory.username=username2 -quarkus.datasource.inventory.jdbc.driver=org.h2.jdbcx.JdbcDataSource -quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp://localhost/mem:inventory -quarkus.datasource.inventory.jdbc.max-size=12 - -# Flyway configuration for default datasource -quarkus.flyway.connect-retries=10 -quarkus.flyway.connect-retries-interval=1000ms -quarkus.flyway.schemas=TEST_SCHEMA -quarkus.flyway.table=flyway_quarkus_history -quarkus.flyway.locations=db/location1,db/location2 -quarkus.flyway.sql-migration-prefix=X -quarkus.flyway.repeatable-sql-migration-prefix=K -quarkus.flyway.migrate-at-start=false -quarkus.flyway.baseline-on-migrate=true -quarkus.flyway.baseline-version=2.0.1 -quarkus.flyway.baseline-description=Initial description -quarkus.flyway.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback - -# Flyway configuration for "users" datasource -quarkus.flyway.users.connect-retries=11 -quarkus.flyway.users.connect-retries-interval=10s -quarkus.flyway.users.schemas=USERS_TEST_SCHEMA -quarkus.flyway.users.table=users_flyway_quarkus_history -quarkus.flyway.users.locations=db/users/location1,db/users/location2 -quarkus.flyway.users.sql-migration-prefix=U -quarkus.flyway.users.repeatable-sql-migration-prefix=S -quarkus.flyway.users.migrate-at-start=false -quarkus.flyway.users.baseline-on-migrate=true -quarkus.flyway.users.baseline-version=2.0.1 -quarkus.flyway.users.baseline-description=Users initial description -quarkus.flyway.users.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback - -# Flyway configuration for "inventory" datasource -quarkus.flyway.inventory.connect-retries=12 -quarkus.flyway.inventory.connect-retries-interval=2s -quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA -quarkus.flyway.inventory.table=inventory_flyway_quarkus_history -quarkus.flyway.inventory.locations=db/inventory/location1,db/inventory/location2 -quarkus.flyway.inventory.sql-migration-prefix=I -quarkus.flyway.inventory.repeatable-sql-migration-prefix=N -quarkus.flyway.inventory.migrate-at-start=false -quarkus.flyway.inventory.baseline-on-migrate=true -quarkus.flyway.inventory.baseline-version=3.0.1 -quarkus.flyway.inventory.baseline-description=Inventory initial description -quarkus.flyway.inventory.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-default.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-default.properties deleted file mode 100644 index 20c1cab3ea521..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-default.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Datasource for "users" -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=username1 -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/mem:users -quarkus.datasource.users.jdbc.max-size=11 - -# Flyway configuration for "users" datasource -quarkus.flyway.users.connect-retries=11 -quarkus.flyway.users.connect-retries-interval=12 -quarkus.flyway.users.schemas=USERS_TEST_SCHEMA -quarkus.flyway.users.table=users_flyway_quarkus_history -quarkus.flyway.users.locations=db/users/location1,db/users/location2 -quarkus.flyway.users.sql-migration-prefix=U -quarkus.flyway.users.repeatable-sql-migration-prefix=S -quarkus.flyway.users.migrate-at-start=false -quarkus.flyway.users.baseline-on-migrate=true -quarkus.flyway.users.baseline-version=2.0.1 -quarkus.flyway.users.baseline-description=Users initial description -quarkus.flyway.users.callbacks=io.quarkus.flyway.multitenant.test.FlywayExtensionCallback diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-flyway.properties b/extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-flyway.properties deleted file mode 100644 index 25294da95bacc..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/config-for-named-datasource-without-flyway.properties +++ /dev/null @@ -1,4 +0,0 @@ -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=sa -quarkus.datasource.users.password=sa -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/mem:test_quarkus;DB_CLOSE_DELAY=-1 diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/db/migration-subfolder/subfolder/V1.0.0__Quarkus.sql b/extensions/flyway-multitenant/deployment/src/test/resources/db/migration-subfolder/subfolder/V1.0.0__Quarkus.sql deleted file mode 100644 index 241cad5122ccb..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/db/migration-subfolder/subfolder/V1.0.0__Quarkus.sql +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE quarked_flyway -( - id INT, - name VARCHAR(20) -); \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.0__Quarkus.sql b/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.0__Quarkus.sql index 241cad5122ccb..8636dad44be86 100644 --- a/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.0__Quarkus.sql +++ b/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.0__Quarkus.sql @@ -1,4 +1,4 @@ -CREATE TABLE quarked_flyway +CREATE TABLE fruit ( id INT, name VARCHAR(20) diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.3__Quarkus_Callback.sql b/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.3__Quarkus_Callback.sql deleted file mode 100644 index 1f46dcd82ef47..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/db/migration/V1.0.3__Quarkus_Callback.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE quarked_callback_2 -( - name VARCHAR(120) -); \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/disabled-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/disabled-config.properties deleted file mode 100644 index 7bf03c9db53df..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/disabled-config.properties +++ /dev/null @@ -1,8 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.enabled=false -quarkus.flyway.migrate-at-start=true diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/h2-init-data.sql b/extensions/flyway-multitenant/deployment/src/test/resources/h2-init-data.sql deleted file mode 100644 index f7bab27cb014f..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/h2-init-data.sql +++ /dev/null @@ -1,3 +0,0 @@ --- We need an existing table in the database to test the creation of the --- Flyway history table with the correct baseline version set. -CREATE TABLE IF NOT EXISTS fake_existing_tbl; \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/h2-init-schema-history-table.sql b/extensions/flyway-multitenant/deployment/src/test/resources/h2-init-schema-history-table.sql deleted file mode 100644 index fafb04b764139..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/h2-init-schema-history-table.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE TABLE "flyway_schema_history" ( - "installed_rank" integer NOT NULL, - "version" character varying(50), - "description" character varying(200) NOT NULL, - "type" character varying(20) NOT NULL, - "script" character varying(1000) NOT NULL, - "checksum" integer, - "installed_by" character varying(100) NOT NULL, - "installed_on" timestamp without time zone DEFAULT now() NOT NULL, - "execution_time" integer NOT NULL, - "success" boolean NOT NULL, - CONSTRAINT flyway_schema_history_pk PRIMARY KEY ("installed_rank") -); \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/init-sql-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/init-sql-config.properties deleted file mode 100644 index a59d04d5e3072..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/init-sql-config.properties +++ /dev/null @@ -1,8 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:init-sql-config;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.migrate-at-start=true -quarkus.flyway.init-sql=CREATE CONSTANT IF NOT EXISTS ONE_HUNDRED VALUE 100 \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config-named-datasource.properties b/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config-named-datasource.properties deleted file mode 100644 index c7ca3a02a4830..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config-named-datasource.properties +++ /dev/null @@ -1,8 +0,0 @@ -#quarkus.log.category."io.quarkus.flyway".level=DEBUG -quarkus.datasource.users.db-kind=h2 -quarkus.datasource.users.username=sa -quarkus.datasource.users.password=sa -quarkus.datasource.users.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start-users;DB_CLOSE_DELAY=-1 - -# Flyway config properties for datasource named users -quarkus.flyway.users.migrate-at-start=true diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config.properties deleted file mode 100644 index 0ba1305214873..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-config.properties +++ /dev/null @@ -1,7 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.migrate-at-start=true diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-multitenancy.properties similarity index 59% rename from extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-config.properties rename to extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-multitenancy.properties index b476e073dc59f..c775fd4df1deb 100644 --- a/extensions/flyway-multitenant/deployment/src/test/resources/baseline-at-start-config.properties +++ b/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-multitenancy.properties @@ -1,8 +1,8 @@ quarkus.datasource.db-kind=h2 quarkus.datasource.username=sa quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-baseline-at-start;DB_CLOSE_DELAY=-1 +quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-schema-multitenancy;DB_CLOSE_DELAY=-1 # Flyway config properties -quarkus.flyway.baseline-at-start=true -quarkus.flyway.baseline-version=1.0.1 \ No newline at end of file +quarkus.flyway.multitenant.migrate-at-start=true +quarkus.hibernate-orm.multitenant=SCHEMA \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-subfolder-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-subfolder-config.properties deleted file mode 100644 index c57bf8416f737..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/migrate-at-start-subfolder-config.properties +++ /dev/null @@ -1,8 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-migrate-at-start-subfolder;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.locations=db/migration-subfolder -quarkus.flyway.migrate-at-start=true diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/named-peristence-unit.properties b/extensions/flyway-multitenant/deployment/src/test/resources/named-peristence-unit.properties new file mode 100644 index 0000000000000..072d5a73be3a5 --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/resources/named-peristence-unit.properties @@ -0,0 +1,12 @@ +quarkus.datasource.db-kind=h2 +quarkus.datasource.username=sa +quarkus.datasource.password=sa +quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-schema-multitenancy;DB_CLOSE_DELAY=-1 + +# Flyway config properties +quarkus.flyway.multitenant.named.baseline-at-start=true +quarkus.flyway.multitenant.named.baseline-version=1.0.1 + +quarkus.hibernate-orm.named.multitenant=SCHEMA +quarkus.hibernate-orm.named.packages=io.quarkus.flyway.multitenant.test +quarkus.hibernate-orm.named.datasource= \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/no-multitenancy.properties b/extensions/flyway-multitenant/deployment/src/test/resources/no-multitenancy.properties new file mode 100644 index 0000000000000..14acc82121e88 --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/resources/no-multitenancy.properties @@ -0,0 +1,8 @@ +quarkus.datasource.db-kind=h2 +quarkus.datasource.username=sa +quarkus.datasource.password=sa +quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-no-multitenancy;DB_CLOSE_DELAY=-1 + +# Flyway config properties +quarkus.flyway.multitenant.baseline-at-start=true +quarkus.flyway.multitenant.baseline-version=1.0.1 \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/repair-at-start-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/repair-at-start-config.properties deleted file mode 100644 index 564b875154758..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/repair-at-start-config.properties +++ /dev/null @@ -1,7 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-repair-at-start;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.migrate-at-start=true diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/schema-multitenancy.properties b/extensions/flyway-multitenant/deployment/src/test/resources/schema-multitenancy.properties new file mode 100644 index 0000000000000..254afb2eff8ad --- /dev/null +++ b/extensions/flyway-multitenant/deployment/src/test/resources/schema-multitenancy.properties @@ -0,0 +1,10 @@ +quarkus.datasource.db-kind=h2 +quarkus.datasource.username=sa +quarkus.datasource.password=sa +quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-schema-multitenancy;DB_CLOSE_DELAY=-1 + +# Flyway config properties +quarkus.flyway.multitenant.baseline-at-start=true +quarkus.flyway.multitenant.baseline-version=1.0.1 + +quarkus.hibernate-orm.multitenant=SCHEMA \ No newline at end of file diff --git a/extensions/flyway-multitenant/deployment/src/test/resources/validate-at-start-config.properties b/extensions/flyway-multitenant/deployment/src/test/resources/validate-at-start-config.properties deleted file mode 100644 index a0810ce17fb35..0000000000000 --- a/extensions/flyway-multitenant/deployment/src/test/resources/validate-at-start-config.properties +++ /dev/null @@ -1,7 +0,0 @@ -quarkus.datasource.db-kind=h2 -quarkus.datasource.username=sa -quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-validate-at-start;DB_CLOSE_DELAY=-1 - -# Flyway config properties -quarkus.flyway.validate-at-start=true diff --git a/extensions/flyway-multitenant/runtime/pom.xml b/extensions/flyway-multitenant/runtime/pom.xml index 51a924effc1de..9344526ae51fd 100644 --- a/extensions/flyway-multitenant/runtime/pom.xml +++ b/extensions/flyway-multitenant/runtime/pom.xml @@ -64,7 +64,7 @@ quarkus-extension-maven-plugin - io.quarkus.flyway + io.quarkus.flyway-multitenant diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantBuildTimeConfig.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantBuildTimeConfig.java index eb1b97ce4e163..f4c0aa29f68cc 100644 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantBuildTimeConfig.java +++ b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantBuildTimeConfig.java @@ -11,7 +11,7 @@ import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; -@ConfigRoot(name = "flyway", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) +@ConfigRoot(name = "flyway.multitenant", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) public final class FlywayMultiTenantBuildTimeConfig { /** diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerProducer.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerProducer.java index 03412a12d9a32..c036676ef1ab2 100644 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerProducer.java +++ b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerProducer.java @@ -2,74 +2,66 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; -import javax.sql.DataSource; - -import io.quarkus.flyway.runtime.FlywayContainer; -import io.quarkus.flyway.runtime.FlywayCreator; -import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; -import io.quarkus.flyway.runtime.FlywayDataSourceRuntimeConfig; -import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.callback.Callback; +import jakarta.enterprise.inject.spi.InjectionPoint; import io.quarkus.arc.All; import io.quarkus.arc.InstanceHandle; - +import io.quarkus.arc.SyntheticCreationalContext; import io.quarkus.flyway.FlywayConfigurationCustomizer; -import io.quarkus.flyway.multitenant.FlywayPersistenceUnit; +import io.quarkus.flyway.runtime.ContainerProducer; +import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; +import io.quarkus.flyway.runtime.FlywayDataSourceRuntimeConfig; +import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil; -/** - * This class is sort of a producer for {@link Flyway}. - * - * It isn't a CDI producer in the literal sense, but it is marked as a bean - * and it's {@code createFlyway} method is called at runtime in order to produce - * the actual {@code Flyway} objects. - * - * CDI scopes and qualifiers are set up at build-time, which is why this class is devoid of - * any CDI annotations - * - */ -public class FlywayMultiTenantContainerProducer { +public class FlywayMultiTenantContainerProducer implements ContainerProducer { private final FlywayMultiTenantRuntimeConfig flywayMultiTenantRuntimeConfig; - private final FlywayMultiTenantBuildTimeConfig flywayBuildConfig; + private final FlywayMultiTenantBuildTimeConfig flywayMultiTenantBuildConfig; private final List> configCustomizerInstances; - public FlywayMultiTenantContainerProducer(FlywayMultiTenantRuntimeConfig flywayMultiTenantRuntimeConfig, - FlywayMultiTenantBuildTimeConfig flywayBuildConfig, + FlywayMultiTenantContainerProducer(FlywayMultiTenantRuntimeConfig flywayMultiTenantRuntimeConfig, + FlywayMultiTenantBuildTimeConfig flywayMultiTenantBuildConfig, @All List> configCustomizerInstances) { + this.flywayMultiTenantRuntimeConfig = flywayMultiTenantRuntimeConfig; - this.flywayBuildConfig = flywayBuildConfig; + this.flywayMultiTenantBuildConfig = flywayMultiTenantBuildConfig; this.configCustomizerInstances = configCustomizerInstances; } - public FlywayContainer createFlyway(DataSource dataSource, String persistenceUnitName, String tenantId, - boolean hasMigrations, - boolean createPossible) { - FlywayDataSourceRuntimeConfig matchingRuntimeConfig = flywayMultiTenantRuntimeConfig - .getConfigForPersistenceUnitName(persistenceUnitName); - FlywayDataSourceBuildTimeConfig matchingBuildTimeConfig = flywayBuildConfig - .getConfigForPersistenceUnitName(persistenceUnitName); - final Collection callbacks = QuarkusPathLocationScanner.callbacksForPersistenceUnit(persistenceUnitName); - final Flyway flyway = new FlywayCreator(matchingRuntimeConfig, matchingBuildTimeConfig, matchingConfigCustomizers( - configCustomizerInstances, persistenceUnitName)).withCallbacks(callbacks) - .withTenantId(tenantId) - .createFlyway(dataSource); - return new FlywayContainer(flyway, matchingRuntimeConfig.baselineAtStart, matchingRuntimeConfig.cleanAtStart, - matchingRuntimeConfig.migrateAtStart, - matchingRuntimeConfig.repairAtStart, matchingRuntimeConfig.validateAtStart, - persistenceUnitName, hasMigrations, - createPossible); + @Override + public String getTenantId(SyntheticCreationalContext context) { + InjectionPoint injectionPoint = context.getInjectedReference(InjectionPoint.class); + FlywayPersistenceUnit annotation = (FlywayPersistenceUnit) injectionPoint.getQualifiers().stream() + .filter(x -> x instanceof FlywayPersistenceUnit) + .findFirst() + .orElseThrow( + () -> new IllegalStateException( + "flyway must be qualified with FlywayPersistenceUnit")); + return annotation.tenantId(); + } + + @Override + public Annotation getFlywayContainerQualifier(String name) { + return FlywayMultiTenantContainerUtil.getFlywayContainerQualifier(name); + } + + @Override + public FlywayDataSourceRuntimeConfig getRuntimeConfig(String name) { + return flywayMultiTenantRuntimeConfig.getConfigForPersistenceUnitName(name); + } + + @Override + public FlywayDataSourceBuildTimeConfig getBuildTimeConfig(String name) { + return flywayMultiTenantBuildConfig.getConfigForPersistenceUnitName(name); } - private List matchingConfigCustomizers( - List> configCustomizerInstances, String persistenceUnitName) { + @Override + public List matchingConfigCustomizers(String persistenceUnitName) { if ((configCustomizerInstances == null) || configCustomizerInstances.isEmpty()) { return Collections.emptyList(); } diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerUtil.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerUtil.java index 4c3a6d7ca0987..35fb548ae2419 100644 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerUtil.java +++ b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayMultiTenantContainerUtil.java @@ -1,11 +1,9 @@ package io.quarkus.flyway.multitenant.runtime; -import io.quarkus.flyway.multitenant.FlywayPersistenceUnit; +import static io.quarkus.flyway.runtime.FlywayCreator.TENANT_ID_DEFAULT; import java.lang.annotation.Annotation; -import static io.quarkus.flyway.runtime.FlywayCreator.TENANT_ID_DEFAULT; - public final class FlywayMultiTenantContainerUtil { private FlywayMultiTenantContainerUtil() { } diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/FlywayPersistenceUnit.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayPersistenceUnit.java similarity index 88% rename from extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/FlywayPersistenceUnit.java rename to extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayPersistenceUnit.java index c115b6502b945..0e257863e8d02 100644 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/FlywayPersistenceUnit.java +++ b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayPersistenceUnit.java @@ -1,7 +1,6 @@ -package io.quarkus.flyway.multitenant; +package io.quarkus.flyway.multitenant.runtime; import static io.quarkus.flyway.runtime.FlywayCreator.TENANT_ID_DEFAULT; -import static io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; @@ -17,6 +16,8 @@ import jakarta.inject.Named; import jakarta.inject.Qualifier; +import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil; + /** * Qualifier used to specify which datasource will be used and therefore which Flyway instance will be injected. *

@@ -29,7 +30,7 @@ @Qualifier public @interface FlywayPersistenceUnit { - String value() default DEFAULT_PERSISTENCE_UNIT_NAME; + String value() default PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME; @Nonbinding String tenantId() default TENANT_ID_DEFAULT; @@ -57,7 +58,7 @@ public static FlywayPersistenceUnitLiteral of(String value, String tenantId) { } public static FlywayPersistenceUnitLiteral ofDefault(String tenantId) { - return new FlywayPersistenceUnitLiteral(DEFAULT_PERSISTENCE_UNIT_NAME, tenantId); + return new FlywayPersistenceUnitLiteral(PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME, tenantId); } @Override diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayRecorder.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayRecorder.java deleted file mode 100644 index 74ebb1a3932b4..0000000000000 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/FlywayRecorder.java +++ /dev/null @@ -1,184 +0,0 @@ -package io.quarkus.flyway.multitenant.runtime; - -import java.util.Collection; -import java.util.Locale; -import java.util.Map; -import java.util.function.Function; - -import javax.sql.DataSource; - -import io.quarkus.flyway.multitenant.FlywayPersistenceUnit; -import io.quarkus.flyway.runtime.FlywayContainer; -import io.quarkus.flyway.runtime.FlywayDataSourceRuntimeConfig; -import io.quarkus.flyway.runtime.UnconfiguredDataSourceFlywayContainer; -import jakarta.enterprise.inject.spi.InjectionPoint; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.FlywayExecutor; -import org.flywaydb.core.api.callback.Callback; -import org.flywaydb.core.api.migration.JavaMigration; -import org.flywaydb.core.api.output.BaselineResult; -import org.flywaydb.core.internal.callback.CallbackExecutor; -import org.flywaydb.core.internal.database.base.Database; -import org.flywaydb.core.internal.database.base.Schema; -import org.flywaydb.core.internal.jdbc.StatementInterceptor; -import org.flywaydb.core.internal.resolver.CompositeMigrationResolver; -import org.flywaydb.core.internal.schemahistory.SchemaHistory; -import org.jboss.logging.Logger; - -import io.quarkus.agroal.runtime.DataSources; -import io.quarkus.agroal.runtime.UnconfiguredDataSource; -import io.quarkus.arc.Arc; -import io.quarkus.arc.InstanceHandle; -import io.quarkus.arc.SyntheticCreationalContext; -import io.quarkus.datasource.common.runtime.DataSourceUtil; -import io.quarkus.runtime.RuntimeValue; -import io.quarkus.runtime.annotations.Recorder; -import io.quarkus.runtime.configuration.ConfigurationException; - -import static io.quarkus.flyway.runtime.FlywayCreator.TENANT_ID_DEFAULT; - -@Recorder -public class FlywayRecorder { - - private static final Logger log = Logger.getLogger(FlywayRecorder.class); - - private final RuntimeValue config; - - public FlywayRecorder(RuntimeValue config) { - this.config = config; - } - - public void setApplicationMigrationFiles(Collection migrationFiles) { - log.debugv("Setting the following application migration files: {0}", migrationFiles); - QuarkusPathLocationScanner.setApplicationMigrationFiles(migrationFiles); - } - - public void setApplicationMigrationClasses(Collection> migrationClasses) { - log.debugv("Setting the following application migration classes: {0}", migrationClasses); - QuarkusPathLocationScanner.setApplicationMigrationClasses(migrationClasses); - } - - public void setApplicationCallbackClasses(Map> callbackClasses) { - log.debugv("Setting application callbacks: {0} total", callbackClasses.values().size()); - QuarkusPathLocationScanner.setApplicationCallbackClasses(callbackClasses); - } - - public Function, FlywayContainer> flywayContainerFunction(String dataSourceName, - String persistenceUnitName, - boolean multiTenant, - boolean hasMigrations, - boolean createPossible) { - return new Function<>() { - @Override - public FlywayContainer apply(SyntheticCreationalContext context) { - DataSource dataSource; - try { - dataSource = context.getInjectedReference(DataSources.class).getDataSource(dataSourceName); - if (dataSource instanceof UnconfiguredDataSource) { - throw DataSourceUtil.dataSourceNotConfigured(dataSourceName); - } - } catch (ConfigurationException e) { - // TODO do we really want to enable retrieval of a FlywayContainer for an unconfigured/inactive datasource? - // Assigning ApplicationScoped to the FlywayContainer - // and throwing UnsatisfiedResolutionException on bean creation (first access) - // would probably make more sense. - return new UnconfiguredDataSourceFlywayContainer(dataSourceName, String.format(Locale.ROOT, - "Unable to find datasource '%s' for Flyway: %s", - dataSourceName, e.getMessage()), e); - } - - String tenantId = getTenantId(multiTenant, context); - FlywayMultiTenantContainerProducer flywayProducer = context - .getInjectedReference(FlywayMultiTenantContainerProducer.class); - return flywayProducer.createFlyway(dataSource, persistenceUnitName, tenantId, hasMigrations, createPossible); - } - }; - } - - public Function, Flyway> flywayFunction(String persistenceUnitName, - boolean multiTenant) { - return new Function<>() { - @Override - public Flyway apply(SyntheticCreationalContext context) { - - String tenantId = getTenantId(multiTenant, context); - FlywayContainer flywayContainer = context.getInjectedReference(FlywayContainer.class, - FlywayMultiTenantContainerUtil.getFlywayContainerQualifier(persistenceUnitName, tenantId)); - return flywayContainer.getFlyway(); - } - }; - } - - public void doStartActions(String persistenceUnitName) { - FlywayDataSourceRuntimeConfig flywayPersistenceUnitRuntimeConfig = config.getValue() - .getConfigForPersistenceUnitName(persistenceUnitName); - - if (!flywayPersistenceUnitRuntimeConfig.active - // If not specified explicitly, Flyway is active when the datasource itself is active. - .orElseGet(() -> Arc.container().instance(DataSources.class).get().getActiveDataSourceNames() - .contains(persistenceUnitName))) { - return; - } - - InstanceHandle flywayContainerInstanceHandle = Arc.container().instance(FlywayContainer.class, - FlywayMultiTenantContainerUtil.getFlywayContainerQualifier(persistenceUnitName)); - - if (!flywayContainerInstanceHandle.isAvailable()) { - return; - } - - FlywayContainer flywayContainer = flywayContainerInstanceHandle.get(); - - if (flywayContainer instanceof UnconfiguredDataSourceFlywayContainer) { - return; - } - - if (flywayContainer.isCleanAtStart()) { - flywayContainer.getFlyway().clean(); - } - if (flywayContainer.isValidateAtStart()) { - flywayContainer.getFlyway().validate(); - } - if (flywayContainer.isBaselineAtStart()) { - new FlywayExecutor(flywayContainer.getFlyway().getConfiguration()) - .execute(new BaselineCommand(flywayContainer.getFlyway()), true, null); - } - if (flywayContainer.isRepairAtStart()) { - flywayContainer.getFlyway().repair(); - } - if (flywayContainer.isMigrateAtStart()) { - flywayContainer.getFlyway().migrate(); - } - } - - private static String getTenantId(boolean multiTenant, SyntheticCreationalContext context) { - if (multiTenant) { - InjectionPoint injectionPoint = context.getInjectedReference(InjectionPoint.class); - FlywayPersistenceUnit annotation = (FlywayPersistenceUnit) injectionPoint.getQualifiers().stream() - .filter(x -> x instanceof FlywayPersistenceUnit) - .findFirst() - .orElseThrow( - () -> new IllegalStateException( - "flyway must be qualified with FlywayPersistenceUnit")); - return annotation.tenantId(); - } - return TENANT_ID_DEFAULT; - } - - static class BaselineCommand implements FlywayExecutor.Command { - BaselineCommand(Flyway flyway) { - this.flyway = flyway; - } - - final Flyway flyway; - - @Override - public BaselineResult execute(CompositeMigrationResolver cmr, SchemaHistory schemaHistory, Database d, - Schema defaultSchema, Schema[] s, CallbackExecutor ce, StatementInterceptor si) { - if (!schemaHistory.exists()) { - return flyway.baseline(); - } - return null; - } - } -} diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayDevUIRecorder.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayDevUIRecorder.java deleted file mode 100644 index f9248883475b1..0000000000000 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayDevUIRecorder.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.quarkus.flyway.multitenant.runtime.devui; - -import java.util.Map; -import java.util.function.Supplier; - -import io.quarkus.arc.Arc; -import io.quarkus.runtime.RuntimeValue; -import io.quarkus.runtime.annotations.Recorder; - -@Recorder -public class FlywayDevUIRecorder { - - public RuntimeValue setInitialSqlSuppliers(Map> initialSqlSuppliers, String artifactId) { - FlywayJsonRpcService rpcService = Arc.container().instance(FlywayJsonRpcService.class).get(); - rpcService.setInitialSqlSuppliers(initialSqlSuppliers); - rpcService.setArtifactId(artifactId); - return new RuntimeValue<>(true); - } - -} diff --git a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayJsonRpcService.java b/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayJsonRpcService.java deleted file mode 100644 index 0830ba8b22b1e..0000000000000 --- a/extensions/flyway-multitenant/runtime/src/main/java/io/quarkus/flyway/multitenant/runtime/devui/FlywayJsonRpcService.java +++ /dev/null @@ -1,231 +0,0 @@ -package io.quarkus.flyway.multitenant.runtime.devui; - -import static java.util.List.of; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -import io.quarkus.flyway.runtime.FlywayContainer; -import io.quarkus.flyway.runtime.FlywayContainersSupplier; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.output.CleanResult; -import org.flywaydb.core.api.output.MigrateResult; - -import io.quarkus.dev.config.CurrentConfig; -import io.quarkus.dev.console.DevConsoleManager; -import io.quarkus.runtime.configuration.ConfigUtils; - -public class FlywayJsonRpcService { - - private Map> initialSqlSuppliers; - private String artifactId; - private Map datasources; - - @ConfigProperty(name = "quarkus.flyway.locations") - private List locations; - - public void setInitialSqlSuppliers(Map> initialSqlSuppliers) { - this.initialSqlSuppliers = initialSqlSuppliers; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public Collection getDatasources() { - if (datasources == null) { - datasources = new HashMap<>(); - Collection flywayContainers = new FlywayContainersSupplier().get(); - for (FlywayContainer fc : flywayContainers) { - datasources.put(fc.getDataSourceName(), - new FlywayDatasource(fc.getDataSourceName(), fc.isHasMigrations(), fc.isCreatePossible())); - } - } - return datasources.values(); - } - - public FlywayActionResponse clean(String ds) { - Flyway flyway = getFlyway(ds); - if (flyway != null) { - CleanResult cleanResult = flyway.clean(); - if (cleanResult.warnings != null && cleanResult.warnings.size() > 0) { - return new FlywayActionResponse("warning", - "Cleaning failed", - cleanResult.warnings.size(), - null, - cleanResult.database, cleanResult.warnings); - } else { - return new FlywayActionResponse("success", - "Cleaned", - cleanResult.schemasCleaned.size(), - null, - cleanResult.database); - } - - } - return errorNoDatasource(ds); - } - - public FlywayActionResponse migrate(String ds) { - Flyway flyway = getFlyway(ds); - if (flyway != null) { - MigrateResult migrateResult = flyway.migrate(); - if (migrateResult.success) { - return new FlywayActionResponse("success", - "Migration executed", - migrateResult.migrationsExecuted, - migrateResult.schemaName, - migrateResult.database); - } else { - return new FlywayActionResponse("warning", - "Migration failed", - migrateResult.warnings.size(), - migrateResult.schemaName, - migrateResult.database, - migrateResult.warnings); - } - } - return errorNoDatasource(ds); - } - - public FlywayActionResponse create(String ds) { - this.getDatasources(); // Make sure we populated the datasources - - Supplier found = initialSqlSuppliers.get(ds); - if (found == null) { - return new FlywayActionResponse("error", "Unable to find SQL generator"); - } - - String script = found.get(); - - Flyway flyway = getFlyway(ds); - if (flyway != null) { - if (script != null) { - Map params = Map.of("ds", ds, "script", script, "artifactId", artifactId); - try { - if (locations.isEmpty()) { - return new FlywayActionResponse("error", "Datasource has no locations configured"); - } - - List resourcesDir = DevConsoleManager.getHotReplacementContext().getResourcesDir(); - if (resourcesDir.isEmpty()) { - return new FlywayActionResponse("error", "No resource directory found"); - } - - // In the current project only - Path path = resourcesDir.get(0); - - Path migrationDir = path.resolve(locations.get(0)); - Files.createDirectories(migrationDir); - Path file = migrationDir.resolve( - "V1.0.0__" + artifactId + ".sql"); - - Files.writeString(file, script); - - FlywayDatasource flywayDatasource = datasources.get(ds); - flywayDatasource.hasMigrations = true; - flywayDatasource.createPossible = false; - Map newConfig = new HashMap<>(); - boolean isBaselineOnMigrateConfigured = ConfigUtils - .isPropertyPresent("quarkus.flyway.baseline-on-migrate"); - boolean isMigrateAtStartConfigured = ConfigUtils.isPropertyPresent("quarkus.flyway.migrate-at-start"); - boolean isCleanAtStartConfigured = ConfigUtils.isPropertyPresent("quarkus.flyway.clean-at-start"); - if (!isBaselineOnMigrateConfigured) { - newConfig.put("quarkus.flyway.baseline-on-migrate", "true"); - } - if (!isMigrateAtStartConfigured) { - newConfig.put("quarkus.flyway.migrate-at-start", "true"); - } - for (var profile : of("test", "dev")) { - if (!isCleanAtStartConfigured) { - newConfig.put("%" + profile + ".quarkus.flyway.clean-at-start", "true"); - } - } - CurrentConfig.EDITOR.accept(newConfig); - //force a scan, to make sure everything is up-to-date - DevConsoleManager.getHotReplacementContext().doScan(true); - return new FlywayActionResponse("success", - "Initial migration created, Flyway will now manage this datasource"); - } catch (Throwable t) { - return new FlywayActionResponse("error", t.getMessage()); - } - } - return errorNoScript(ds); - } - return errorNoDatasource(ds); - } - - public int getNumberOfDatasources() { - Collection flywayContainers = new FlywayContainersSupplier().get(); - return flywayContainers.size(); - } - - private FlywayActionResponse errorNoDatasource(String ds) { - return new FlywayActionResponse("error", "Flyway datasource not found [" + ds + "]"); - } - - private FlywayActionResponse errorNoScript(String ds) { - return new FlywayActionResponse("error", "Missing Flyway initial script for [" + ds + "]"); - } - - private Flyway getFlyway(String ds) { - Collection flywayContainers = new FlywayContainersSupplier().get(); - for (FlywayContainer flywayContainer : flywayContainers) { - if (flywayContainer.getDataSourceName().equals(ds)) { - return flywayContainer.getFlyway(); - } - } - return null; - } - - public static class FlywayDatasource { - public String name; - public boolean hasMigrations; - public boolean createPossible; - - public FlywayDatasource() { - } - - public FlywayDatasource(String name, boolean hasMigrations, boolean createPossible) { - this.name = name; - this.hasMigrations = hasMigrations; - this.createPossible = createPossible; - } - } - - public static class FlywayActionResponse { - public String type; - public String message; - public int number; - public String schema; - public String database; - public List warnings; - - public FlywayActionResponse() { - } - - public FlywayActionResponse(String type, String message) { - this(type, message, -1, null, null, List.of()); - } - - public FlywayActionResponse(String type, String message, int number, String schema, String database) { - this(type, message, number, schema, database, List.of()); - } - - public FlywayActionResponse(String type, String message, int number, String schema, String database, - List warnings) { - this.type = type; - this.message = message; - this.number = number; - this.schema = schema; - this.database = database; - this.warnings = warnings; - } - } -} diff --git a/extensions/flyway-multitenant/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/flyway-multitenant/runtime/src/main/resources/META-INF/quarkus-extension.yaml index cc2fe5ca69a8c..5ad3289269bf1 100644 --- a/extensions/flyway-multitenant/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/flyway-multitenant/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -1,6 +1,6 @@ --- artifact: ${project.groupId}:${project.artifactId}:${project.version} -name: "Flyway" +name: "Flyway MultiTenant" metadata: keywords: - "flyway" @@ -11,4 +11,4 @@ metadata: - "data" status: "stable" config: - - "quarkus.flyway." + - "quarkus.flyway.multitenant." diff --git a/extensions/flyway-multitenant/runtime/src/test/java/io/quarkus/flyway/multitenant/runtime/FlywayCreatorTest.java b/extensions/flyway-multitenant/runtime/src/test/java/io/quarkus/flyway/multitenant/runtime/FlywayCreatorTest.java deleted file mode 100644 index eb2c4e9f599ff..0000000000000 --- a/extensions/flyway-multitenant/runtime/src/test/java/io/quarkus/flyway/multitenant/runtime/FlywayCreatorTest.java +++ /dev/null @@ -1,295 +0,0 @@ -package io.quarkus.flyway.multitenant.runtime; - -import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.OptionalInt; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import io.quarkus.flyway.runtime.FlywayCreator; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.Location; -import org.flywaydb.core.api.configuration.Configuration; -import org.flywaydb.core.api.pattern.ValidatePattern; -import org.flywaydb.core.internal.util.ValidatePatternUtils; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class FlywayCreatorTest { - - private FlywayPersistenceUnitRuntimeConfig runtimeConfig = FlywayPersistenceUnitRuntimeConfig.defaultConfig(); - private FlywayPersistenceUnitBuildTimeConfig buildConfig = FlywayPersistenceUnitBuildTimeConfig.defaultConfig(); - private Configuration defaultConfig = Flyway.configure().load().getConfiguration(); - - /** - * class under test. - */ - private FlywayCreator creator; - - @Test - @DisplayName("locations default matches flyway default") - void testLocationsDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(pathList(defaultConfig.getLocations()), pathList(createdFlywayConfig().getLocations())); - } - - @Test - @DisplayName("locations carried over from configuration") - void testLocationsOverridden() { - buildConfig.locations = Arrays.asList("db/migrations", "db/something"); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(buildConfig.locations, pathList(createdFlywayConfig().getLocations())); - } - - @Test - @DisplayName("not configured locations replaced by default") - void testNotPresentLocationsOverridden() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(pathList(defaultConfig.getLocations()), pathList(createdFlywayConfig().getLocations())); - } - - @Test - @DisplayName("baseline description default matches flyway default") - void testBaselineDescriptionDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(defaultConfig.getBaselineDescription(), createdFlywayConfig().getBaselineDescription()); - } - - @Test - @DisplayName("baseline description carried over from configuration") - void testBaselineDescriptionOverridden() { - runtimeConfig.baselineDescription = Optional.of("baselineDescription"); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.baselineDescription.get(), createdFlywayConfig().getBaselineDescription()); - } - - @Test - @DisplayName("baseline version default matches flyway default") - void testBaselineVersionDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(defaultConfig.getBaselineVersion(), createdFlywayConfig().getBaselineVersion()); - } - - @Test - @DisplayName("baseline version carried over from configuration") - void testBaselineVersionOverridden() { - runtimeConfig.baselineVersion = Optional.of("0.1.2"); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.baselineVersion.get(), createdFlywayConfig().getBaselineVersion().getVersion()); - } - - @Test - @DisplayName("connection retries default matches flyway default") - void testConnectionRetriesDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(defaultConfig.getConnectRetries(), createdFlywayConfig().getConnectRetries()); - } - - @Test - @DisplayName("connection retries carried over from configuration") - void testConnectionRetriesOverridden() { - runtimeConfig.connectRetries = OptionalInt.of(12); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.connectRetries.getAsInt(), createdFlywayConfig().getConnectRetries()); - } - - @Test - @DisplayName("repeatable SQL migration prefix default matches flyway default") - void testRepeatableSqlMigrationPrefixDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(defaultConfig.getRepeatableSqlMigrationPrefix(), createdFlywayConfig().getRepeatableSqlMigrationPrefix()); - } - - @Test - @DisplayName("repeatable SQL migration prefix carried over from configuration") - void testRepeatableSqlMigrationPrefixOverridden() { - runtimeConfig.repeatableSqlMigrationPrefix = Optional.of("A"); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.repeatableSqlMigrationPrefix.get(), createdFlywayConfig().getRepeatableSqlMigrationPrefix()); - } - - @Test - @DisplayName("schemas default matches flyway default") - void testSchemasDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(asList(defaultConfig.getSchemas()), asList(createdFlywayConfig().getSchemas())); - } - - @Test - @DisplayName("schemas carried over from configuration") - void testSchemasOverridden() { - runtimeConfig.schemas = Optional.of(Arrays.asList("TEST_SCHEMA_1", "TEST_SCHEMA_2")); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.schemas.get(), asList(createdFlywayConfig().getSchemas())); - } - - @Test - @DisplayName("SQL migration prefix default matches flyway default") - void testSqlMigrationPrefixDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(defaultConfig.getSqlMigrationPrefix(), createdFlywayConfig().getSqlMigrationPrefix()); - } - - @Test - @DisplayName("SQL migration prefix carried over from configuration") - void testSqlMigrationPrefixOverridden() { - runtimeConfig.sqlMigrationPrefix = Optional.of("M"); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.sqlMigrationPrefix.get(), createdFlywayConfig().getSqlMigrationPrefix()); - } - - @Test - @DisplayName("table default matches flyway default") - void testTableDefault() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(defaultConfig.getTable(), createdFlywayConfig().getTable()); - } - - @Test - @DisplayName("table carried over from configuration") - void testTableOverridden() { - runtimeConfig.table = Optional.of("flyway_history_test_table"); - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.table.get(), createdFlywayConfig().getTable()); - } - - @Test - @DisplayName("validate on migrate default matches to true") - void testValidateOnMigrate() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.validateOnMigrate, createdFlywayConfig().isValidateOnMigrate()); - assertTrue(runtimeConfig.validateOnMigrate); - } - - @Test - @DisplayName("clean disabled default matches to false") - void testCleanDisabled() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.cleanDisabled, createdFlywayConfig().isCleanDisabled()); - assertFalse(runtimeConfig.cleanDisabled); - - runtimeConfig.cleanDisabled = false; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertFalse(createdFlywayConfig().isCleanDisabled()); - - runtimeConfig.cleanDisabled = true; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertTrue(createdFlywayConfig().isCleanDisabled()); - } - - @Test - @DisplayName("outOfOrder is correctly set") - void testOutOfOrder() { - runtimeConfig.outOfOrder = false; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertFalse(createdFlywayConfig().isOutOfOrder()); - - runtimeConfig.outOfOrder = true; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertTrue(createdFlywayConfig().isOutOfOrder()); - } - - @Test - @DisplayName("ignoreMissingMigrations is correctly set") - void testIgnoreMissingMigrations() { - runtimeConfig.ignoreMissingMigrations = false; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertFalse(ValidatePatternUtils.isMissingIgnored(createdFlywayConfig().getIgnoreMigrationPatterns())); - - runtimeConfig.ignoreMissingMigrations = true; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertTrue(ValidatePatternUtils.isMissingIgnored(createdFlywayConfig().getIgnoreMigrationPatterns())); - } - - @Test - @DisplayName("ignoreFutureMigrations is correctly set") - void testIgnoreFutureMigrations() { - runtimeConfig.ignoreFutureMigrations = false; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertFalse(ValidatePatternUtils.isFutureIgnored(createdFlywayConfig().getIgnoreMigrationPatterns())); - - runtimeConfig.ignoreFutureMigrations = true; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertTrue(ValidatePatternUtils.isFutureIgnored(createdFlywayConfig().getIgnoreMigrationPatterns())); - } - - @Test - @DisplayName("cleanOnValidationError defaults to false and is correctly set") - void testCleanOnValidationError() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.cleanOnValidationError, createdFlywayConfig().isCleanOnValidationError()); - assertFalse(runtimeConfig.cleanOnValidationError); - - runtimeConfig.cleanOnValidationError = false; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertFalse(createdFlywayConfig().isCleanOnValidationError()); - - runtimeConfig.cleanOnValidationError = true; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertTrue(createdFlywayConfig().isCleanOnValidationError()); - } - - @ParameterizedTest - @MethodSource("validateOnMigrateOverwritten") - @DisplayName("validate on migrate overwritten in configuration") - void testValidateOnMigrateOverwritten(final boolean input, final boolean expected) { - runtimeConfig.validateOnMigrate = input; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(createdFlywayConfig().isValidateOnMigrate(), expected); - assertEquals(runtimeConfig.validateOnMigrate, expected); - } - - @Test - @DisplayName("validateMigrationNaming defaults to false and it is correctly set") - void testValidateMigrationNaming() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(runtimeConfig.validateMigrationNaming, createdFlywayConfig().isValidateMigrationNaming()); - assertFalse(runtimeConfig.validateMigrationNaming); - - runtimeConfig.validateMigrationNaming = true; - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertTrue(createdFlywayConfig().isValidateMigrationNaming()); - } - - @Test - @DisplayName("validateIgnoreMigrationPatterns defaults to false and it is correctly set") - void testIgnoreMigrationPatterns() { - creator = new FlywayCreator(runtimeConfig, buildConfig); - assertEquals(0, createdFlywayConfig().getIgnoreMigrationPatterns().length); - assertFalse(runtimeConfig.ignoreMigrationPatterns.isPresent()); - - runtimeConfig.ignoreMigrationPatterns = Optional.of(new String[] { "*:missing" }); - creator = new FlywayCreator(runtimeConfig, buildConfig); - final ValidatePattern[] existingIgnoreMigrationPatterns = createdFlywayConfig().getIgnoreMigrationPatterns(); - assertEquals(1, existingIgnoreMigrationPatterns.length); - final String[] ignoreMigrationPatterns = runtimeConfig.ignoreMigrationPatterns.get(); - final ValidatePattern[] validatePatterns = Arrays.stream(ignoreMigrationPatterns) - .map(ValidatePattern::fromPattern).toArray(ValidatePattern[]::new); - assertArrayEquals(validatePatterns, existingIgnoreMigrationPatterns); - } - - private static List pathList(Location[] locations) { - return Stream.of(locations).map(Location::getPath).collect(Collectors.toList()); - } - - private Configuration createdFlywayConfig() { - return creator.createFlyway(null).getConfiguration(); - } - - private static Stream validateOnMigrateOverwritten() { - return Stream. builder() - .add(Arguments.arguments(false, false)) - .add(Arguments.arguments(true, true)) - .build(); - } -} diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayBuildItem.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayBuildItem.java new file mode 100644 index 0000000000000..112f24126ed46 --- /dev/null +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayBuildItem.java @@ -0,0 +1,70 @@ +package io.quarkus.flyway.deployment; + +import org.jboss.jandex.AnnotationInstance; + +import io.quarkus.builder.item.MultiBuildItem; +import io.quarkus.flyway.runtime.ContainerProducer; +import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; + +public final class FlywayBuildItem extends MultiBuildItem { + + public FlywayBuildItem(String name, String dataSourceName, boolean multiTenancyEnabled, + FlywayDataSourceBuildTimeConfig buildTimeConfig, AnnotationInstance qualifier, String flywayBeanName, + String containerBeanName, int priority, Class multiTenancySupport) { + this.name = name; + this.dataSourceName = dataSourceName; + this.multiTenancyEnabled = multiTenancyEnabled; + this.buildTimeConfig = buildTimeConfig; + this.qualifier = qualifier; + this.flywayBeanName = flywayBeanName; + this.containerBeanName = containerBeanName; + this.priority = priority; + this.multiTenancySupport = multiTenancySupport; + } + + private final String name; + private final String dataSourceName; + private final boolean multiTenancyEnabled; + private final FlywayDataSourceBuildTimeConfig buildTimeConfig; + private final AnnotationInstance qualifier; + private final String flywayBeanName; + private final String containerBeanName; + private final int priority; + private final Class multiTenancySupport; + + public String getName() { + return name; + } + + public String getDataSourceName() { + return dataSourceName; + } + + public boolean isMultiTenancyEnabled() { + return multiTenancyEnabled; + } + + public FlywayDataSourceBuildTimeConfig getBuildTimeConfig() { + return buildTimeConfig; + } + + public AnnotationInstance getQualifier() { + return qualifier; + } + + public int getPriority() { + return priority; + } + + public String getFlywayBeanName() { + return flywayBeanName; + } + + public String getContainerBeanName() { + return containerBeanName; + } + + public Class getMultiTenancySupport() { + return multiTenancySupport; + } +} diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java index 92e5a125affc5..242fbecaf1ab9 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java @@ -18,29 +18,26 @@ import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.builditem.CombinedIndexBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; -import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; /** * Logic to locate and process Flyway {@link Callback} classes. * This class also helps to keep the {@link FlywayProcessor} class as lean as possible to make it easier to maintain */ class FlywayCallbacksLocator { - private final Collection dataSourceNames; - private final FlywayBuildTimeConfig flywayBuildConfig; + private final Collection flywayBuildItems; private final CombinedIndexBuildItem combinedIndexBuildItem; private final BuildProducer reflectiveClassProducer; - private FlywayCallbacksLocator(Collection dataSourceNames, FlywayBuildTimeConfig flywayBuildConfig, + private FlywayCallbacksLocator(Collection flywayBuildItems, CombinedIndexBuildItem combinedIndexBuildItem, BuildProducer reflectiveClassProducer) { - this.dataSourceNames = dataSourceNames; - this.flywayBuildConfig = flywayBuildConfig; + this.flywayBuildItems = flywayBuildItems; this.combinedIndexBuildItem = combinedIndexBuildItem; this.reflectiveClassProducer = reflectiveClassProducer; } - public static FlywayCallbacksLocator with(Collection dataSourceNames, FlywayBuildTimeConfig flywayBuildConfig, + public static FlywayCallbacksLocator with(Collection flywayBuildItems, CombinedIndexBuildItem combinedIndexBuildItem, BuildProducer reflectiveClassProducer) { - return new FlywayCallbacksLocator(dataSourceNames, flywayBuildConfig, combinedIndexBuildItem, reflectiveClassProducer); + return new FlywayCallbacksLocator(flywayBuildItems, combinedIndexBuildItem, reflectiveClassProducer); } /** @@ -56,9 +53,9 @@ public static FlywayCallbacksLocator with(Collection dataSourceNames, Fl public Map> getCallbacks() throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException { final Map> callbacks = new HashMap<>(); - for (String dataSourceName : dataSourceNames) { - final Collection instances = callbacksForDataSource(dataSourceName); - callbacks.put(dataSourceName, instances); + for (FlywayBuildItem flywayBuildItem : flywayBuildItems) { + final Collection instances = callbacksFor(flywayBuildItem); + callbacks.put(flywayBuildItem.getName(), instances); } return callbacks; } @@ -74,9 +71,9 @@ public Map> getCallbacks() * @exception IllegalAccessException if the {@link Callback} constructor is enforcing Java language access control * and the underlying constructor is inaccessible */ - private Collection callbacksForDataSource(String dataSourceName) + private Collection callbacksFor(FlywayBuildItem flywayBuildItem) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException { - final Optional> callbackConfig = flywayBuildConfig.getConfigForDataSourceName(dataSourceName).callbacks; + final Optional> callbackConfig = flywayBuildItem.getBuildTimeConfig().callbacks; if (!callbackConfig.isPresent()) { return Collections.emptyList(); } diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java index cd37ff8462667..58a9467d5c450 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java @@ -18,7 +18,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Default; +import jakarta.enterprise.inject.spi.InjectionPoint; import jakarta.inject.Singleton; import org.flywaydb.core.Flyway; @@ -105,6 +107,36 @@ void reflection(CombinedIndexBuildItem index, BuildProducer flywayBuildItems, List jdbcDataSourceBuildItems, + FlywayBuildTimeConfig flywayBuildTimeConfig) { + for (JdbcDataSourceBuildItem item : jdbcDataSourceBuildItems) { + String dataSourceName = item.getName(); + FlywayDataSourceBuildTimeConfig buildTimeConfig = flywayBuildTimeConfig + .getConfigForDataSourceName(dataSourceName); + AnnotationInstance qualifier; + int priority; + String flywayBeanName = null; + String containerBeanName = null; + + if (DataSourceUtil.isDefault(dataSourceName)) { + // Flyway containers used to be ordered with the default database coming first. + // Some multitenant tests are relying on this order. + priority = 10; + qualifier = AnnotationInstance.builder(Default.class).build(); + } else { + priority = 5; + qualifier = AnnotationInstance.builder(FlywayDataSource.class).add("value", dataSourceName) + .build(); + flywayBeanName = FLYWAY_BEAN_NAME_PREFIX + dataSourceName; + containerBeanName = FLYWAY_CONTAINER_BEAN_NAME_PREFIX + dataSourceName; + } + + flywayBuildItems.produce(new FlywayBuildItem(dataSourceName, dataSourceName, false, buildTimeConfig, qualifier, + flywayBeanName, containerBeanName, priority, FlywayContainerProducer.class)); + } + } + @Record(STATIC_INIT) @BuildStep MigrationStateBuildItem build(BuildProducer resourceProducer, @@ -113,18 +145,15 @@ MigrationStateBuildItem build(BuildProducer resour FlywayRecorder recorder, RecorderContext context, CombinedIndexBuildItem combinedIndexBuildItem, - List jdbcDataSourceBuildItems, - FlywayBuildTimeConfig flywayBuildTimeConfig) throws Exception { + List flywayBuildItems) throws Exception { - Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); Map> applicationMigrationsToDs = new HashMap<>(); - for (var dataSourceName : dataSourceNames) { - FlywayDataSourceBuildTimeConfig flywayDataSourceBuildTimeConfig = flywayBuildTimeConfig - .getConfigForDataSourceName(dataSourceName); + for (var flywayBuildItem : flywayBuildItems) { + FlywayDataSourceBuildTimeConfig flywayDataSourceBuildTimeConfig = flywayBuildItem.getBuildTimeConfig(); Collection migrationLocations = discoverApplicationMigrations( flywayDataSourceBuildTimeConfig.locations); - applicationMigrationsToDs.put(dataSourceName, migrationLocations); + applicationMigrationsToDs.put(flywayBuildItem.getName(), migrationLocations); } Set datasourcesWithMigrations = new HashSet<>(); Set datasourcesWithoutMigrations = new HashSet<>(); @@ -156,8 +185,7 @@ MigrationStateBuildItem build(BuildProducer resour recorder.setApplicationMigrationClasses(javaMigrationClasses); final Map> callbacks = FlywayCallbacksLocator.with( - dataSourceNames, - flywayBuildTimeConfig, + flywayBuildItems, combinedIndexBuildItem, reflectiveClassProducer).getCallbacks(); recorder.setApplicationCallbackClasses(callbacks); @@ -185,79 +213,72 @@ private void addJavaMigrations(Collection candidates, RecorderContext @Consume(LoggingSetupBuildItem.class) @Record(ExecutionTime.RUNTIME_INIT) void createBeans(FlywayRecorder recorder, - List jdbcDataSourceBuildItems, + List flywayBuildItems, List sqlGeneratorBuildItems, BuildProducer additionalBeans, BuildProducer syntheticBeanBuildItemBuildProducer, MigrationStateBuildItem migrationsBuildItem, FlywayBuildTimeConfig flywayBuildTimeConfig) { // make a FlywayContainerProducer bean + additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClasses(FlywayContainerProducer.class).setUnremovable() .setDefaultScope(DotNames.SINGLETON).build()); + // add the @FlywayDataSource class otherwise it won't be registered as a qualifier additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClass(FlywayDataSource.class).build()); - Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); - - for (String dataSourceName : dataSourceNames) { - boolean hasMigrations = migrationsBuildItem.hasMigrations.contains(dataSourceName); + for (FlywayBuildItem flywayBuildItem : flywayBuildItems) { + boolean hasMigrations = migrationsBuildItem.hasMigrations.contains(flywayBuildItem.getName()); boolean createPossible = false; if (!hasMigrations) { - createPossible = sqlGeneratorBuildItems.stream().anyMatch(s -> s.getDatabaseName().equals(dataSourceName)); + createPossible = sqlGeneratorBuildItems.stream() + .anyMatch(s -> s.getDatabaseName().equals(flywayBuildItem.getDataSourceName())); } - SyntheticBeanBuildItem.ExtendedBeanConfigurator flywayContainerConfigurator = SyntheticBeanBuildItem .configure(FlywayContainer.class) .scope(Singleton.class) .setRuntimeInit() .unremovable() - .addInjectionPoint(ClassType.create(DotName.createSimple(FlywayContainerProducer.class))) + .addInjectionPoint(ClassType.create(DotName.createSimple(flywayBuildItem.getMultiTenancySupport()))) .addInjectionPoint(ClassType.create(DotName.createSimple(DataSources.class))) - .createWith(recorder.flywayContainerFunction(dataSourceName, hasMigrations, createPossible)); - - AnnotationInstance flywayContainerQualifier; - - if (DataSourceUtil.isDefault(dataSourceName)) { - flywayContainerConfigurator.addQualifier(Default.class); - - // Flyway containers used to be ordered with the default database coming first. - // Some multitenant tests are relying on this order. - flywayContainerConfigurator.priority(10); + .createWith(recorder.flywayContainerFunction(flywayBuildItem.getDataSourceName(), flywayBuildItem.getName(), + flywayBuildItem.isMultiTenancyEnabled(), flywayBuildItem.getMultiTenancySupport(), hasMigrations, + createPossible)); - flywayContainerQualifier = AnnotationInstance.builder(Default.class).build(); - } else { - String beanName = FLYWAY_CONTAINER_BEAN_NAME_PREFIX + dataSourceName; - flywayContainerConfigurator.name(beanName); + flywayContainerConfigurator.addQualifier(flywayBuildItem.getQualifier()); + flywayContainerConfigurator.priority(flywayBuildItem.getPriority()); - flywayContainerConfigurator.addQualifier().annotation(DotNames.NAMED).addValue("value", beanName).done(); - flywayContainerConfigurator.addQualifier().annotation(FlywayDataSource.class).addValue("value", dataSourceName) - .done(); - flywayContainerConfigurator.priority(5); - - flywayContainerQualifier = AnnotationInstance.builder(FlywayDataSource.class).add("value", dataSourceName) - .build(); + if (flywayBuildItem.getContainerBeanName() != null) { + flywayContainerConfigurator.name(flywayBuildItem.getContainerBeanName()); + flywayContainerConfigurator.addQualifier().annotation(DotNames.NAMED) + .addValue("value", flywayBuildItem.getContainerBeanName()).done(); } syntheticBeanBuildItemBuildProducer.produce(flywayContainerConfigurator.done()); SyntheticBeanBuildItem.ExtendedBeanConfigurator flywayConfigurator = SyntheticBeanBuildItem .configure(Flyway.class) - .scope(Singleton.class) + .scope(flywayBuildItem.isMultiTenancyEnabled() ? Dependent.class : Singleton.class) .setRuntimeInit() .unremovable() - .addInjectionPoint(ClassType.create(DotName.createSimple(FlywayContainer.class)), flywayContainerQualifier) - .createWith(recorder.flywayFunction(dataSourceName)); + .addInjectionPoint(ClassType.create(DotName.createSimple(flywayBuildItem.getMultiTenancySupport()))) + .addInjectionPoint(ClassType.create(DotName.createSimple(FlywayContainer.class)), + flywayBuildItem.getQualifier()) + .createWith(recorder.flywayFunction(flywayBuildItem.getName(), flywayBuildItem.isMultiTenancyEnabled(), + flywayBuildItem.getMultiTenancySupport())); + + if (flywayBuildItem.isMultiTenancyEnabled()) { + flywayConfigurator.addInjectionPoint( + ClassType.create(DotName.createSimple(InjectionPoint.class))); + } - if (DataSourceUtil.isDefault(dataSourceName)) { - flywayConfigurator.addQualifier(Default.class); - flywayConfigurator.priority(10); - } else { - String beanName = FLYWAY_BEAN_NAME_PREFIX + dataSourceName; - flywayConfigurator.name(beanName); - flywayConfigurator.priority(5); + flywayConfigurator.addQualifier(flywayBuildItem.getQualifier()); + flywayConfigurator.priority(flywayBuildItem.getPriority()); - flywayConfigurator.addQualifier().annotation(DotNames.NAMED).addValue("value", beanName).done(); - flywayConfigurator.addQualifier().annotation(FlywayDataSource.class).addValue("value", dataSourceName).done(); + if (flywayBuildItem.getFlywayBeanName() != null) { + flywayConfigurator.name(flywayBuildItem.getFlywayBeanName()); + flywayConfigurator.addQualifier().annotation(DotNames.NAMED) + .addValue("value", flywayBuildItem.getFlywayBeanName()).done(); } syntheticBeanBuildItemBuildProducer.produce(flywayConfigurator.done()); @@ -271,13 +292,11 @@ public ServiceStartBuildItem startActions(FlywayRecorder recorder, FlywayRuntimeConfig config, BuildProducer schemaReadyBuildItem, BuildProducer initializationCompleteBuildItem, - List jdbcDataSourceBuildItems, + List flywayBuildItems, MigrationStateBuildItem migrationsBuildItem) { - Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); - - for (String dataSourceName : dataSourceNames) { - recorder.doStartActions(dataSourceName); + for (FlywayBuildItem flywayBuildItem : flywayBuildItems) { + recorder.doStartActions(flywayBuildItem.getName(), flywayBuildItem.getMultiTenancySupport()); } // once we are done running the migrations, we produce a build item indicating that the @@ -297,14 +316,6 @@ public InitTaskBuildItem configureInitTask(ApplicationInfoBuildItem app) { .withSharedFilesystem(true); } - private Set getDataSourceNames(List jdbcDataSourceBuildItems) { - Set result = new HashSet<>(jdbcDataSourceBuildItems.size()); - for (JdbcDataSourceBuildItem item : jdbcDataSourceBuildItems) { - result.add(item.getName()); - } - return result; - } - private Collection discoverApplicationMigrations(Collection locations) throws IOException { LinkedHashSet applicationMigrationResources = new LinkedHashSet<>(); diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/FlywayTenantSupport.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/FlywayTenantSupport.java new file mode 100644 index 0000000000000..c1e53d2c29abb --- /dev/null +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/FlywayTenantSupport.java @@ -0,0 +1,8 @@ +package io.quarkus.flyway; + +import java.util.List; + +public interface FlywayTenantSupport { + + List getTenantsToInitialize(); +} diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/ContainerProducer.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/ContainerProducer.java new file mode 100644 index 0000000000000..62c2d9af85dd6 --- /dev/null +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/ContainerProducer.java @@ -0,0 +1,20 @@ +package io.quarkus.flyway.runtime; + +import java.lang.annotation.Annotation; +import java.util.List; + +import io.quarkus.arc.SyntheticCreationalContext; +import io.quarkus.flyway.FlywayConfigurationCustomizer; + +public interface ContainerProducer { + + String getTenantId(SyntheticCreationalContext context); + + Annotation getFlywayContainerQualifier(String name); + + FlywayDataSourceBuildTimeConfig getBuildTimeConfig(String name); + + FlywayDataSourceRuntimeConfig getRuntimeConfig(String name); + + List matchingConfigCustomizers(String dataSourceName); +} diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainer.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainer.java index cc952cb0f15aa..a796d27cbf693 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainer.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainer.java @@ -1,11 +1,16 @@ package io.quarkus.flyway.runtime; +import javax.sql.DataSource; + import org.flywaydb.core.Flyway; public class FlywayContainer { - private final Flyway flyway; + private final FlywayCreator flyway; + + private final DataSource dataSource; + private final boolean multiTenancyEnabled; private final boolean baselineAtStart; private final boolean cleanAtStart; private final boolean migrateAtStart; @@ -17,10 +22,13 @@ public class FlywayContainer { private final boolean createPossible; private final String id; - public FlywayContainer(Flyway flyway, boolean baselineAtStart, boolean cleanAtStart, boolean migrateAtStart, + public FlywayContainer(FlywayCreator flyway, DataSource dataSource, boolean baselineAtStart, boolean cleanAtStart, + boolean migrateAtStart, boolean repairAtStart, boolean validateAtStart, - String dataSourceName, boolean hasMigrations, boolean createPossible) { + String dataSourceName, String name, boolean multiTenancyEnabled, boolean hasMigrations, boolean createPossible) { this.flyway = flyway; + this.dataSource = dataSource; + this.multiTenancyEnabled = multiTenancyEnabled; this.baselineAtStart = baselineAtStart; this.cleanAtStart = cleanAtStart; this.migrateAtStart = migrateAtStart; @@ -29,11 +37,22 @@ public FlywayContainer(Flyway flyway, boolean baselineAtStart, boolean cleanAtSt this.dataSourceName = dataSourceName; this.hasMigrations = hasMigrations; this.createPossible = createPossible; - this.id = dataSourceName.replace("<", "").replace(">", ""); + this.id = name.replace("<", "").replace(">", ""); } public Flyway getFlyway() { - return flyway; + return flyway.createFlyway(dataSource); + } + + public Flyway getFlyway(String tenantId) { + if (!isMultiTenancyEnabled()) { + throw new RuntimeException("Multi-tenancy is not enabled"); + } + return flyway.createFlyway(dataSource, tenantId); + } + + public boolean isMultiTenancyEnabled() { + return multiTenancyEnabled; } public boolean isBaselineAtStart() { diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainerProducer.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainerProducer.java index fe921bdf6a9a3..2707a4f6b10e8 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainerProducer.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayContainerProducer.java @@ -2,64 +2,54 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; -import javax.sql.DataSource; - -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.callback.Callback; - import io.quarkus.arc.All; import io.quarkus.arc.InstanceHandle; +import io.quarkus.arc.SyntheticCreationalContext; import io.quarkus.datasource.common.runtime.DataSourceUtil; import io.quarkus.flyway.FlywayConfigurationCustomizer; import io.quarkus.flyway.FlywayDataSource; -/** - * This class is sort of a producer for {@link Flyway}. - * - * It isn't a CDI producer in the literal sense, but it is marked as a bean - * and it's {@code createFlyway} method is called at runtime in order to produce - * the actual {@code Flyway} objects. - * - * CDI scopes and qualifiers are set up at build-time, which is why this class is devoid of - * any CDI annotations - * - */ -public class FlywayContainerProducer { +public class FlywayContainerProducer implements ContainerProducer { private final FlywayRuntimeConfig flywayRuntimeConfig; private final FlywayBuildTimeConfig flywayBuildConfig; private final List> configCustomizerInstances; - public FlywayContainerProducer(FlywayRuntimeConfig flywayRuntimeConfig, FlywayBuildTimeConfig flywayBuildConfig, + FlywayContainerProducer(FlywayRuntimeConfig flywayRuntimeConfig, FlywayBuildTimeConfig flywayBuildConfig, @All List> configCustomizerInstances) { + this.flywayRuntimeConfig = flywayRuntimeConfig; this.flywayBuildConfig = flywayBuildConfig; this.configCustomizerInstances = configCustomizerInstances; } - public FlywayContainer createFlyway(DataSource dataSource, String dataSourceName, boolean hasMigrations, - boolean createPossible) { - FlywayDataSourceRuntimeConfig matchingRuntimeConfig = flywayRuntimeConfig.getConfigForDataSourceName(dataSourceName); - FlywayDataSourceBuildTimeConfig matchingBuildTimeConfig = flywayBuildConfig.getConfigForDataSourceName(dataSourceName); - final Collection callbacks = QuarkusPathLocationScanner.callbacksForDataSource(dataSourceName); - final Flyway flyway = new FlywayCreator(matchingRuntimeConfig, matchingBuildTimeConfig, matchingConfigCustomizers( - configCustomizerInstances, dataSourceName)).withCallbacks(callbacks) - .createFlyway(dataSource); - return new FlywayContainer(flyway, matchingRuntimeConfig.baselineAtStart, matchingRuntimeConfig.cleanAtStart, - matchingRuntimeConfig.migrateAtStart, - matchingRuntimeConfig.repairAtStart, matchingRuntimeConfig.validateAtStart, - dataSourceName, hasMigrations, - createPossible); + @Override + public String getTenantId(SyntheticCreationalContext context) { + throw new RuntimeException("Multitenancy is not enabled"); + } + + @Override + public Annotation getFlywayContainerQualifier(String name) { + return FlywayContainerUtil.getFlywayContainerQualifier(name); + } + + @Override + public FlywayDataSourceRuntimeConfig getRuntimeConfig(String name) { + return flywayRuntimeConfig.getConfigForDataSourceName(name); + } + + @Override + public FlywayDataSourceBuildTimeConfig getBuildTimeConfig(String name) { + return flywayBuildConfig.getConfigForDataSourceName(name); } - private List matchingConfigCustomizers( - List> configCustomizerInstances, String dataSourceName) { + @Override + public List matchingConfigCustomizers(String dataSourceName) { if ((configCustomizerInstances == null) || configCustomizerInstances.isEmpty()) { return Collections.emptyList(); } diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayCreator.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayCreator.java index a2048955dc810..42cd159f8254e 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayCreator.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayCreator.java @@ -27,7 +27,6 @@ public class FlywayCreator { private final FlywayDataSourceBuildTimeConfig flywayBuildTimeConfig; private final List customizers; private Collection callbacks = Collections.emptyList(); - private String tenantId = TENANT_ID_DEFAULT; // only used for tests public FlywayCreator(FlywayDataSourceRuntimeConfig flywayRuntimeConfig, @@ -50,12 +49,11 @@ public FlywayCreator withCallbacks(Collection callbacks) { return this; } - public FlywayCreator withTenantId(String tenantId) { - this.tenantId = tenantId; - return this; + public Flyway createFlyway(DataSource dataSource) { + return createFlyway(dataSource, TENANT_ID_DEFAULT); } - public Flyway createFlyway(DataSource dataSource) { + public Flyway createFlyway(DataSource dataSource, String tenantId) { FluentConfiguration configure = Flyway.configure(); if (flywayRuntimeConfig.jdbcUrl.isPresent()) { diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java index 3af211f682891..94045eaa18db8 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java @@ -1,6 +1,7 @@ package io.quarkus.flyway.runtime; import java.util.Collection; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; @@ -26,6 +27,7 @@ import io.quarkus.arc.InstanceHandle; import io.quarkus.arc.SyntheticCreationalContext; import io.quarkus.datasource.common.runtime.DataSourceUtil; +import io.quarkus.flyway.FlywayTenantSupport; import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; import io.quarkus.runtime.configuration.ConfigurationException; @@ -57,7 +59,8 @@ public void setApplicationCallbackClasses(Map> call } public Function, FlywayContainer> flywayContainerFunction(String dataSourceName, - boolean hasMigrations, + String name, boolean multiTenancyEnabled, + Class containerProducerClass, boolean hasMigrations, boolean createPossible) { return new Function<>() { @Override @@ -73,41 +76,53 @@ public FlywayContainer apply(SyntheticCreationalContext context // Assigning ApplicationScoped to the FlywayContainer // and throwing UnsatisfiedResolutionException on bean creation (first access) // would probably make more sense. - return new UnconfiguredDataSourceFlywayContainer(dataSourceName, String.format(Locale.ROOT, + return new UnconfiguredDataSourceFlywayContainer(dataSourceName, name, String.format(Locale.ROOT, "Unable to find datasource '%s' for Flyway: %s", dataSourceName, e.getMessage()), e); } - FlywayContainerProducer flywayProducer = context.getInjectedReference(FlywayContainerProducer.class); - return flywayProducer.createFlyway(dataSource, dataSourceName, hasMigrations, createPossible); + ContainerProducer containerProducer = context.getInjectedReference(containerProducerClass); + + FlywayDataSourceRuntimeConfig matchingRuntimeConfig = containerProducer.getRuntimeConfig(name); + FlywayDataSourceBuildTimeConfig matchingBuildTimeConfig = containerProducer.getBuildTimeConfig(name); + final Collection callbacks = QuarkusPathLocationScanner.callbacksForDataSource(name); + final FlywayCreator flyway = new FlywayCreator(matchingRuntimeConfig, matchingBuildTimeConfig, + containerProducer.matchingConfigCustomizers(name)) + .withCallbacks(callbacks); + return new FlywayContainer(flyway, dataSource, matchingRuntimeConfig.baselineAtStart, + matchingRuntimeConfig.cleanAtStart, + matchingRuntimeConfig.migrateAtStart, + matchingRuntimeConfig.repairAtStart, matchingRuntimeConfig.validateAtStart, + dataSourceName, name, multiTenancyEnabled, hasMigrations, + createPossible); } }; } - public Function, Flyway> flywayFunction(String dataSourceName) { + public Function, Flyway> flywayFunction(String name, boolean multiTenancyEnabled, + Class containerProducerClass) { return new Function<>() { @Override public Flyway apply(SyntheticCreationalContext context) { + ContainerProducer containerProducer = context.getInjectedReference(containerProducerClass); FlywayContainer flywayContainer = context.getInjectedReference(FlywayContainer.class, - FlywayContainerUtil.getFlywayContainerQualifier(dataSourceName)); + containerProducer.getFlywayContainerQualifier(name)); + if (multiTenancyEnabled) { + return flywayContainer.getFlyway(containerProducer.getTenantId(context)); + } return flywayContainer.getFlyway(); } }; } - public void doStartActions(String dataSourceName) { - FlywayDataSourceRuntimeConfig flywayDataSourceRuntimeConfig = config.getValue() - .getConfigForDataSourceName(dataSourceName); + public void doStartActions(String name, Class containerProducerClass) { - if (!flywayDataSourceRuntimeConfig.active - // If not specified explicitly, Flyway is active when the datasource itself is active. - .orElseGet(() -> Arc.container().instance(DataSources.class).get().getActiveDataSourceNames() - .contains(dataSourceName))) { - return; - } + ContainerProducer containerProducer = Arc.container().instance(containerProducerClass).get(); + + FlywayDataSourceRuntimeConfig flywayDataSourceRuntimeConfig = containerProducer.getRuntimeConfig(name); InstanceHandle flywayContainerInstanceHandle = Arc.container().instance(FlywayContainer.class, - FlywayContainerUtil.getFlywayContainerQualifier(dataSourceName)); + containerProducer.getFlywayContainerQualifier(name)); if (!flywayContainerInstanceHandle.isAvailable()) { return; @@ -115,25 +130,49 @@ public void doStartActions(String dataSourceName) { FlywayContainer flywayContainer = flywayContainerInstanceHandle.get(); + if (!flywayDataSourceRuntimeConfig.active + // If not specified explicitly, Flyway is active when the datasource itself is active. + .orElseGet(() -> Arc.container().instance(DataSources.class).get().getActiveDataSourceNames() + .contains(flywayContainer.getDataSourceName()))) { + return; + } + if (flywayContainer instanceof UnconfiguredDataSourceFlywayContainer) { return; } + if (flywayContainer.isMultiTenancyEnabled()) { + InstanceHandle tenantSupportInstance = Arc.container().instance(FlywayTenantSupport.class); + if (!tenantSupportInstance.isAvailable()) { + return; + } + FlywayTenantSupport flywayTenantSupport = tenantSupportInstance.get(); + List tenantsToInitialize = flywayTenantSupport.getTenantsToInitialize(); + if (tenantsToInitialize == null || tenantsToInitialize.isEmpty()) { + return; + } + tenantsToInitialize.forEach(tenantId -> initialize(flywayContainer, flywayContainer.getFlyway(tenantId))); + } else { + initialize(flywayContainer, flywayContainer.getFlyway()); + } + } + + private static void initialize(FlywayContainer flywayContainer, Flyway flyway) { if (flywayContainer.isCleanAtStart()) { - flywayContainer.getFlyway().clean(); + flyway.clean(); } if (flywayContainer.isValidateAtStart()) { - flywayContainer.getFlyway().validate(); + flyway.validate(); } if (flywayContainer.isBaselineAtStart()) { - new FlywayExecutor(flywayContainer.getFlyway().getConfiguration()) - .execute(new BaselineCommand(flywayContainer.getFlyway()), true, null); + new FlywayExecutor(flyway.getConfiguration()) + .execute(new BaselineCommand(flyway), true, null); } if (flywayContainer.isRepairAtStart()) { - flywayContainer.getFlyway().repair(); + flyway.repair(); } if (flywayContainer.isMigrateAtStart()) { - flywayContainer.getFlyway().migrate(); + flyway.migrate(); } } diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/UnconfiguredDataSourceFlywayContainer.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/UnconfiguredDataSourceFlywayContainer.java index 5011c9898ce0d..d3198aedc40a1 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/UnconfiguredDataSourceFlywayContainer.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/UnconfiguredDataSourceFlywayContainer.java @@ -7,8 +7,8 @@ public class UnconfiguredDataSourceFlywayContainer extends FlywayContainer { private final String message; private final Throwable cause; - public UnconfiguredDataSourceFlywayContainer(String dataSourceName, String message, Throwable cause) { - super(null, false, false, false, false, false, dataSourceName, false, false); + public UnconfiguredDataSourceFlywayContainer(String dataSourceName, String name, String message, Throwable cause) { + super(null, null, false, false, false, false, false, dataSourceName, name, false, false, false); this.message = message; this.cause = cause; }