From f6027e8080cd6ea583498898816251af934bce48 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 25 Aug 2023 21:00:03 +0200 Subject: [PATCH 1/5] Rework how to enable/activate Flyway --- .../flyway/FlywayAlwaysEnabledProcessor.java | 44 ++++++++++++++ .../java/io/quarkus/flyway/FlywayEnabled.java | 24 ++++++++ .../io/quarkus/flyway/FlywayProcessor.java | 57 +++++-------------- .../flyway/runtime/FlywayBuildTimeConfig.java | 10 ++++ .../FlywayDataSourceRuntimeConfig.java | 6 ++ .../flyway/runtime/FlywayRecorder.java | 8 +-- .../flyway/runtime/FlywayRuntimeConfig.java | 7 --- 7 files changed, 103 insertions(+), 53 deletions(-) create mode 100644 extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java create mode 100644 extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java new file mode 100644 index 0000000000000..54a2023318acc --- /dev/null +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java @@ -0,0 +1,44 @@ +package io.quarkus.flyway; + +import org.flywaydb.core.extensibility.Plugin; + +import io.quarkus.deployment.Feature; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.IndexDependencyBuildItem; +import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; + +public class FlywayAlwaysEnabledProcessor { + + @BuildStep + void build(BuildProducer featureProducer) { + featureProducer.produce(new FeatureBuildItem(Feature.FLYWAY)); + } + + /** + * Reinitialize {@code InsertRowLock} to avoid using a cached seed when invoking {@code getNextRandomString} + */ + @BuildStep + public RuntimeReinitializedClassBuildItem reinitInsertRowLock() { + return new RuntimeReinitializedClassBuildItem( + "org.flywaydb.core.internal.database.InsertRowLock"); + } + + @BuildStep + public NativeImageResourceBuildItem resources() { + return new NativeImageResourceBuildItem("org/flywaydb/database/version.txt"); + } + + @BuildStep + IndexDependencyBuildItem indexFlyway() { + return new IndexDependencyBuildItem("org.flywaydb", "flyway-core"); + } + + @BuildStep + public ServiceProviderBuildItem flywayPlugins() { + return ServiceProviderBuildItem.allProvidersFromClassPath(Plugin.class.getName()); + } +} diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java new file mode 100644 index 0000000000000..18060719451c6 --- /dev/null +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java @@ -0,0 +1,24 @@ +package io.quarkus.flyway; + +import java.util.function.BooleanSupplier; + +import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; + +/** + * Supplier that can be used to only run build steps + * if the Flyway extension is enabled. + */ +public class FlywayEnabled implements BooleanSupplier { + + private final FlywayBuildTimeConfig config; + + FlywayEnabled(FlywayBuildTimeConfig config) { + this.config = config; + } + + @Override + public boolean getAsBoolean() { + return config.enabled; + } + +} diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java index 1fb06fce2b9c2..61740d5cd0652 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java @@ -25,7 +25,6 @@ import org.flywaydb.core.api.Location; import org.flywaydb.core.api.callback.Callback; import org.flywaydb.core.api.migration.JavaMigration; -import org.flywaydb.core.extensibility.Plugin; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.ClassType; @@ -43,34 +42,32 @@ import io.quarkus.arc.processor.DotNames; import io.quarkus.builder.item.SimpleBuildItem; import io.quarkus.datasource.common.runtime.DataSourceUtil; -import io.quarkus.deployment.Feature; 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.FeatureBuildItem; import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem; -import io.quarkus.deployment.builditem.IndexDependencyBuildItem; 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.builditem.nativeimage.RuntimeReinitializedClassBuildItem; -import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; import io.quarkus.deployment.logging.LoggingSetupBuildItem; import io.quarkus.deployment.recording.RecorderContext; import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayContainer; import io.quarkus.flyway.runtime.FlywayContainerProducer; +import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayRecorder; import io.quarkus.flyway.runtime.FlywayRuntimeConfig; import io.quarkus.runtime.util.ClassPathUtils; +@BuildSteps(onlyIf = FlywayEnabled.class) class FlywayProcessor { private static final String CLASSPATH_APPLICATION_MIGRATIONS_PROTOCOL = "classpath"; @@ -82,32 +79,26 @@ class FlywayProcessor { private static final Logger LOGGER = Logger.getLogger(FlywayProcessor.class); - FlywayBuildTimeConfig flywayBuildConfig; - - @BuildStep - IndexDependencyBuildItem indexFlyway() { - return new IndexDependencyBuildItem("org.flywaydb", "flyway-core"); - } - @Record(STATIC_INIT) @BuildStep - MigrationStateBuildItem build(BuildProducer featureProducer, - BuildProducer resourceProducer, + MigrationStateBuildItem build(BuildProducer resourceProducer, BuildProducer reflectiveClassProducer, BuildProducer hotDeploymentProducer, FlywayRecorder recorder, RecorderContext context, CombinedIndexBuildItem combinedIndexBuildItem, - List jdbcDataSourceBuildItems) throws Exception { - - featureProducer.produce(new FeatureBuildItem(Feature.FLYWAY)); + List jdbcDataSourceBuildItems, + FlywayBuildTimeConfig flywayBuildTimeConfig) throws Exception { Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); Map> applicationMigrationsToDs = new HashMap<>(); - for (var i : dataSourceNames) { + for (var dataSourceName : dataSourceNames) { + FlywayDataSourceBuildTimeConfig flywayDataSourceBuildTimeConfig = flywayBuildTimeConfig + .getConfigForDataSourceName(dataSourceName); + Collection migrationLocations = discoverApplicationMigrations( - flywayBuildConfig.getConfigForDataSourceName(i).locations); - applicationMigrationsToDs.put(i, migrationLocations); + flywayDataSourceBuildTimeConfig.locations); + applicationMigrationsToDs.put(dataSourceName, migrationLocations); } Set datasourcesWithMigrations = new HashSet<>(); Set datasourcesWithoutMigrations = new HashSet<>(); @@ -138,7 +129,7 @@ MigrationStateBuildItem build(BuildProducer featureProducer, final Map> callbacks = FlywayCallbacksLocator.with( dataSourceNames, - flywayBuildConfig, + flywayBuildTimeConfig, combinedIndexBuildItem, reflectiveClassProducer).getCallbacks(); recorder.setApplicationCallbackClasses(callbacks); @@ -170,7 +161,8 @@ void createBeans(FlywayRecorder recorder, List sqlGeneratorBuildItems, BuildProducer additionalBeans, BuildProducer syntheticBeanBuildItemBuildProducer, - MigrationStateBuildItem migrationsBuildItem) { + MigrationStateBuildItem migrationsBuildItem, + FlywayBuildTimeConfig flywayBuildTimeConfig) { // make a FlywayContainerProducer bean additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClasses(FlywayContainerProducer.class).setUnremovable() .setDefaultScope(DotNames.SINGLETON).build()); @@ -341,25 +333,6 @@ private Set getApplicationMigrationsFromPath(final String location, fina } } - /** - * Reinitialize {@code InsertRowLock} to avoid using a cached seed when invoking {@code getNextRandomString} - */ - @BuildStep - public RuntimeReinitializedClassBuildItem reinitInsertRowLock() { - return new RuntimeReinitializedClassBuildItem( - "org.flywaydb.core.internal.database.InsertRowLock"); - } - - @BuildStep - public NativeImageResourceBuildItem resources() { - return new NativeImageResourceBuildItem("org/flywaydb/database/version.txt"); - } - - @BuildStep - public ServiceProviderBuildItem flywayPlugins() { - return ServiceProviderBuildItem.allProvidersFromClassPath(Plugin.class.getName()); - } - public static final class MigrationStateBuildItem extends SimpleBuildItem { final Set hasMigrations; diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java index 47e7a4878c7f4..5560e96941cc4 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java @@ -21,6 +21,16 @@ public FlywayDataSourceBuildTimeConfig getConfigForDataSourceName(String dataSou return namedDataSources.getOrDefault(dataSourceName, FlywayDataSourceBuildTimeConfig.defaultConfig()); } + /** + * Whether Flyway is enabled *during the build*. + * + * If Flyway is disabled, the Flyway beans won't be created and Flyway won't be usable. + * + * @asciidoclet + */ + @ConfigItem(defaultValue = "true") + public boolean enabled; + /** * Flyway configuration for the default datasource. */ diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java index 79f4c961a0e5a..726ada0de89fd 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java @@ -22,6 +22,12 @@ public static FlywayDataSourceRuntimeConfig defaultConfig() { return new FlywayDataSourceRuntimeConfig(); } + /** + * Flag to activate/deactivate Flyway for a specific datasource at runtime. + */ + @ConfigItem(defaultValue = "true") + public boolean active = true; + /** * The maximum number of retries when attempting to connect to the database. *

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 2bb0fffb51c72..8200a4b18d730 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 @@ -96,13 +96,13 @@ public Flyway apply(SyntheticCreationalContext context) { } public void doStartActions() { - if (!config.getValue().enabled) { - return; - } - for (InstanceHandle flywayContainerHandle : Arc.container().listAll(FlywayContainer.class)) { FlywayContainer flywayContainer = flywayContainerHandle.get(); + if (!config.getValue().getConfigForDataSourceName(flywayContainer.getDataSourceName()).active) { + return; + } + if (flywayContainer.isCleanAtStart()) { flywayContainer.getFlyway().clean(); } diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java index 481ee6e821539..703e3cd0b00a1 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java @@ -21,13 +21,6 @@ public FlywayDataSourceRuntimeConfig getConfigForDataSourceName(String dataSourc return namedDataSources.getOrDefault(dataSourceName, FlywayDataSourceRuntimeConfig.defaultConfig()); } - /** - * Flag to enable / disable Flyway. - * - */ - @ConfigItem(defaultValue = "true") - public boolean enabled; - /** * Flyway configuration for the default datasource. */ From 28cf0b8f1d4299d100f4eeafddaca954a3dbe688 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 4 Sep 2023 17:31:26 +0200 Subject: [PATCH 2/5] Do not load the FlywayContainer bean if not active --- .../io/quarkus/flyway/FlywayProcessor.java | 7 +- .../flyway/runtime/FlywayRecorder.java | 70 +++++++++++-------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java index 61740d5cd0652..950894ff35b16 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java @@ -243,9 +243,14 @@ public ServiceStartBuildItem startActions(FlywayRecorder recorder, FlywayRuntimeConfig config, BuildProducer schemaReadyBuildItem, BuildProducer initializationCompleteBuildItem, + List jdbcDataSourceBuildItems, MigrationStateBuildItem migrationsBuildItem) { - recorder.doStartActions(); + Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); + + for (String dataSourceName : dataSourceNames) { + recorder.doStartActions(dataSourceName); + } // once we are done running the migrations, we produce a build item indicating that the // schema is "ready" 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 8200a4b18d730..7f82c9a5c3036 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 @@ -82,44 +82,54 @@ public Function, Flyway> flywayFunction(Strin return new Function<>() { @Override public Flyway apply(SyntheticCreationalContext context) { - Annotation flywayContainerQualifier; - if (DataSourceUtil.isDefault(dataSourceName)) { - flywayContainerQualifier = Default.Literal.INSTANCE; - } else { - flywayContainerQualifier = FlywayDataSourceLiteral.of(dataSourceName); - } - - FlywayContainer flywayContainer = context.getInjectedReference(FlywayContainer.class, flywayContainerQualifier); + FlywayContainer flywayContainer = context.getInjectedReference(FlywayContainer.class, + getFlywayContainerQualifier(dataSourceName)); return flywayContainer.getFlyway(); } }; } - public void doStartActions() { - for (InstanceHandle flywayContainerHandle : Arc.container().listAll(FlywayContainer.class)) { - FlywayContainer flywayContainer = flywayContainerHandle.get(); + public void doStartActions(String dataSourceName) { + FlywayDataSourceRuntimeConfig flywayDataSourceRuntimeConfig = config.getValue() + .getConfigForDataSourceName(dataSourceName); - if (!config.getValue().getConfigForDataSourceName(flywayContainer.getDataSourceName()).active) { - return; - } + if (!config.getValue().getConfigForDataSourceName(dataSourceName).active) { + 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(); - } + InstanceHandle flywayContainerInstanceHandle = Arc.container().instance(FlywayContainer.class, + getFlywayContainerQualifier(dataSourceName)); + + if (!flywayContainerInstanceHandle.isAvailable()) { + return; } + + FlywayContainer flywayContainer = flywayContainerInstanceHandle.get(); + + 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 Annotation getFlywayContainerQualifier(String dataSourceName) { + if (DataSourceUtil.isDefault(dataSourceName)) { + return Default.Literal.INSTANCE; + } + + return FlywayDataSourceLiteral.of(dataSourceName); } static class BaselineCommand implements FlywayExecutor.Command { From 797162aa9a97cecabf6155d64df18bfa0a2f581d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 5 Sep 2023 18:01:52 +0200 Subject: [PATCH 3/5] Better handle the UnconfiguredDataSource case I wasn't exactly aware of this new development and it needs to be handled a bit differently. --- .../quarkus/flyway/runtime/FlywayRecorder.java | 7 +++++-- .../UnconfiguredDataSourceFlywayContainer.java | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/UnconfiguredDataSourceFlywayContainer.java 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 7f82c9a5c3036..f8df08e4e7825 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 @@ -8,7 +8,6 @@ import javax.sql.DataSource; import jakarta.enterprise.inject.Default; -import jakarta.enterprise.inject.UnsatisfiedResolutionException; import org.flywaydb.core.Flyway; import org.flywaydb.core.FlywayExecutor; @@ -67,7 +66,7 @@ public Function, FlywayContainer> fl public FlywayContainer apply(SyntheticCreationalContext context) { DataSource dataSource = context.getInjectedReference(DataSources.class).getDataSource(dataSourceName); if (dataSource instanceof UnconfiguredDataSource) { - throw new UnsatisfiedResolutionException("No datasource present"); + return new UnconfiguredDataSourceFlywayContainer(dataSourceName); } FlywayContainerProducer flywayProducer = context.getInjectedReference(FlywayContainerProducer.class); @@ -106,6 +105,10 @@ public void doStartActions(String dataSourceName) { FlywayContainer flywayContainer = flywayContainerInstanceHandle.get(); + if (flywayContainer instanceof UnconfiguredDataSourceFlywayContainer) { + return; + } + if (flywayContainer.isCleanAtStart()) { flywayContainer.getFlyway().clean(); } 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 new file mode 100644 index 0000000000000..a3206cd8141ae --- /dev/null +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/UnconfiguredDataSourceFlywayContainer.java @@ -0,0 +1,16 @@ +package io.quarkus.flyway.runtime; + +import org.flywaydb.core.Flyway; + +public class UnconfiguredDataSourceFlywayContainer extends FlywayContainer { + + public UnconfiguredDataSourceFlywayContainer(String dataSourceName) { + super(null, false, false, false, false, false, dataSourceName, false, false); + } + + @Override + public Flyway getFlyway() { + throw new UnsupportedOperationException( + "Cannot get a Flyway instance for unconfigured datasource " + getDataSourceName()); + } +} From e0f9964af1db4792f4861e358f4c13a67f27886f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Sep 2023 10:36:36 +0200 Subject: [PATCH 4/5] Avoid split packages in Flyway extension --- .../flyway/{ => deployment}/FlywayAlwaysEnabledProcessor.java | 2 +- .../flyway/{ => deployment}/FlywayCallbacksLocator.java | 2 +- .../java/io/quarkus/flyway/{ => deployment}/FlywayEnabled.java | 2 +- .../io/quarkus/flyway/{ => deployment}/FlywayProcessor.java | 3 ++- .../flyway/{ => deployment}/devui/FlywayDevUIProcessor.java | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) rename extensions/flyway/deployment/src/main/java/io/quarkus/flyway/{ => deployment}/FlywayAlwaysEnabledProcessor.java (97%) rename extensions/flyway/deployment/src/main/java/io/quarkus/flyway/{ => deployment}/FlywayCallbacksLocator.java (99%) rename extensions/flyway/deployment/src/main/java/io/quarkus/flyway/{ => deployment}/FlywayEnabled.java (92%) rename extensions/flyway/deployment/src/main/java/io/quarkus/flyway/{ => deployment}/FlywayProcessor.java (99%) rename extensions/flyway/deployment/src/main/java/io/quarkus/flyway/{ => deployment}/devui/FlywayDevUIProcessor.java (97%) diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayAlwaysEnabledProcessor.java similarity index 97% rename from extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java rename to extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayAlwaysEnabledProcessor.java index 54a2023318acc..bff1407d07cf1 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayAlwaysEnabledProcessor.java @@ -1,4 +1,4 @@ -package io.quarkus.flyway; +package io.quarkus.flyway.deployment; import org.flywaydb.core.extensibility.Plugin; diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayCallbacksLocator.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java similarity index 99% rename from extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayCallbacksLocator.java rename to extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java index 8d90513e8de45..92e5a125affc5 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayCallbacksLocator.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java @@ -1,4 +1,4 @@ -package io.quarkus.flyway; +package io.quarkus.flyway.deployment; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayEnabled.java similarity index 92% rename from extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java rename to extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayEnabled.java index 18060719451c6..928e009e8ef16 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayEnabled.java @@ -1,4 +1,4 @@ -package io.quarkus.flyway; +package io.quarkus.flyway.deployment; import java.util.function.BooleanSupplier; diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java similarity index 99% rename from extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java rename to extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java index 950894ff35b16..ecd2439175b89 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayProcessor.java @@ -1,4 +1,4 @@ -package io.quarkus.flyway; +package io.quarkus.flyway.deployment; import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT; @@ -59,6 +59,7 @@ 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.runtime.FlywayBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayContainer; import io.quarkus.flyway.runtime.FlywayContainerProducer; diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/devui/FlywayDevUIProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/devui/FlywayDevUIProcessor.java similarity index 97% rename from extensions/flyway/deployment/src/main/java/io/quarkus/flyway/devui/FlywayDevUIProcessor.java rename to extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/devui/FlywayDevUIProcessor.java index e1d1c7cfcb838..90dd8c6ad9e19 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/devui/FlywayDevUIProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/devui/FlywayDevUIProcessor.java @@ -1,4 +1,4 @@ -package io.quarkus.flyway.devui; +package io.quarkus.flyway.deployment.devui; import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT; From 88e50c2fe7b0700b7ffa235fcf5c2dd774229d53 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Sep 2023 11:50:06 +0200 Subject: [PATCH 5/5] Add tests for enabled/active in Flyway extension --- ...OnMigrateNamedDataSourcesInactiveTest.java | 70 +++++++++++++++++++ .../test/FlywayExtensionDisabledTest.java | 31 ++++++++ ...rate-named-datasources-inactive.properties | 24 +++++++ .../test/resources/disabled-config.properties | 8 +++ 4 files changed, 133 insertions(+) create mode 100644 extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java create mode 100644 extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionDisabledTest.java create mode 100644 extensions/flyway/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties create mode 100644 extensions/flyway/deployment/src/test/resources/disabled-config.properties diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java new file mode 100644 index 0000000000000..f4b5fb39d1c18 --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineOnMigrateNamedDataSourcesInactiveTest.java @@ -0,0 +1,70 @@ +package io.quarkus.flyway.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/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionDisabledTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionDisabledTest.java new file mode 100644 index 0000000000000..c5fa111d1074f --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionDisabledTest.java @@ -0,0 +1,31 @@ +package io.quarkus.flyway.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/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties b/extensions/flyway/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties new file mode 100644 index 0000000000000..d816d7b5a8451 --- /dev/null +++ b/extensions/flyway/deployment/src/test/resources/baseline-on-migrate-named-datasources-inactive.properties @@ -0,0 +1,24 @@ +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/deployment/src/test/resources/disabled-config.properties b/extensions/flyway/deployment/src/test/resources/disabled-config.properties new file mode 100644 index 0000000000000..7bf03c9db53df --- /dev/null +++ b/extensions/flyway/deployment/src/test/resources/disabled-config.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:test-quarkus-migrate-at-start;DB_CLOSE_DELAY=-1 + +# Flyway config properties +quarkus.flyway.enabled=false +quarkus.flyway.migrate-at-start=true