Skip to content

Commit

Permalink
Support custom Flyway credentials and URL
Browse files Browse the repository at this point in the history
- Introduces `quarkus.flyway.username`, `quarkus.flyway.password` and `quarkus.flyway.jdbc-url` config options

Co-Authored-By: George Gastaldi <[email protected]>
Co-Authored-By: Guillaume Smet <[email protected]>
  • Loading branch information
3 people committed Jan 27, 2023
1 parent b62572d commit e7d1d24
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import org.flywaydb.core.api.callback.Callback;
import org.flywaydb.core.api.configuration.FluentConfiguration;

import io.agroal.api.AgroalDataSource;
import io.quarkus.flyway.FlywayConfigurationCustomizer;
import io.quarkus.runtime.configuration.ConfigurationException;

class FlywayCreator {

Expand Down Expand Up @@ -46,7 +48,28 @@ public FlywayCreator withCallbacks(Collection<Callback> callbacks) {

public Flyway createFlyway(DataSource dataSource) {
FluentConfiguration configure = Flyway.configure();
configure.dataSource(dataSource);

if (flywayRuntimeConfig.jdbcUrl.isPresent()) {
if (flywayRuntimeConfig.username.isPresent() && flywayRuntimeConfig.password.isPresent()) {
configure.dataSource(flywayRuntimeConfig.jdbcUrl.get(), flywayRuntimeConfig.username.get(),
flywayRuntimeConfig.password.get());
} else {
throw new ConfigurationException(
"Username and password must be defined when a JDBC URL is provided in the Flyway configuration");
}
} else {
if (flywayRuntimeConfig.username.isPresent() && flywayRuntimeConfig.password.isPresent()) {
AgroalDataSource agroalDataSource = (AgroalDataSource) dataSource;
String jdbcUrl = agroalDataSource.getConfiguration().connectionPoolConfiguration()
.connectionFactoryConfiguration().jdbcUrl();

configure.dataSource(jdbcUrl, flywayRuntimeConfig.username.get(),
flywayRuntimeConfig.password.get());
} else {

configure.dataSource(dataSource);
}
}
if (flywayRuntimeConfig.initSql.isPresent()) {
configure.initSql(flywayRuntimeConfig.initSql.get());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ public static FlywayDataSourceRuntimeConfig defaultConfig() {
@ConfigItem
public Optional<String> defaultSchema = Optional.empty();

/**
* The JDBC URL that Flyway uses to connect to the database.
* Falls back to the datasource URL if not specified.
*/
@ConfigItem
public Optional<String> jdbcUrl = Optional.empty();

/**
* The username that Flyway uses to connect to the database.
* If no specific JDBC URL is configured, falls back to the datasource username if not specified.
*/
@ConfigItem
public Optional<String> username = Optional.empty();

/**
* The password that Flyway uses to connect to the database.
* If no specific JDBC URL is configured, falls back to the datasource password if not specified.
*/
@ConfigItem
public Optional<String> password = Optional.empty();

/**
* Comma-separated case-sensitive list of schemas managed by Flyway.
* The first schema in the list will be automatically set as the default one during the migration.
Expand Down
15 changes: 8 additions & 7 deletions integration-tests/flyway/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2</artifactId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
Expand All @@ -39,11 +45,6 @@
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
Expand Down Expand Up @@ -85,7 +86,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2-deployment</artifactId>
<artifactId>quarkus-jdbc-postgresql-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class AppEntity {

private String name;

private String createdBy;

public int getId() {
return id;
}
Expand All @@ -34,6 +36,14 @@ public void setName(final String name) {
this.name = name;
}

public String getCreatedBy() {
return createdBy;
}

public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}

@Override
public boolean equals(final Object o) {
if (this == o)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,15 @@ public String returnInitSql() {
@GET
@Path("init-sql-result")
public Integer returnInitSqlResult() {
return (Integer) entityManager.createNativeQuery("SELECT ONE_HUNDRED")
return (Integer) entityManager.createNativeQuery("SELECT f_my_constant()")
.getSingleResult();
}

@GET
@Path("created-by")
public String returnCreatedByUser() {
return entityManager.createQuery("select a from AppEntity a where a.id = 1", AppEntity.class)
.getSingleResult().getCreatedBy();
}

}
18 changes: 10 additions & 8 deletions integration-tests/flyway/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
quarkus.log.console.level=DEBUG
quarkus.log.category."org.flywaydb.core".level=DEBUG
quarkus.log.category."io.quarkus.flyway".level=DEBUG

# Agroal config
quarkus.datasource.db-kind=h2
quarkus.datasource.username=sa
quarkus.datasource.password=sa
quarkus.datasource.db-kind=postgresql
quarkus.datasource.devservices.init-script-path=initdb.sql


# default flyway configuration properties
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test_quarkus;DB_CLOSE_DELAY=-1
quarkus.flyway.connect-retries=10
quarkus.flyway.schemas=TEST_SCHEMA
quarkus.flyway.table=flyway_quarkus_history
quarkus.flyway.username=scott
quarkus.flyway.password=tiger

# spaces should be trimmed
quarkus.flyway.locations= db/location1 , classpath:db/location2, classpath:/db/location4
quarkus.flyway.sql-migration-prefix=V
Expand All @@ -19,16 +22,15 @@ quarkus.flyway.placeholders.foo=bar
quarkus.flyway.placeholders.title=REPLACED
quarkus.flyway.placeholder-prefix=#[
quarkus.flyway.placeholder-suffix=]
quarkus.flyway.init-sql=CREATE CONSTANT IF NOT EXISTS ONE_HUNDRED VALUE 100

quarkus.flyway.init-sql=CREATE SCHEMA IF NOT EXISTS TEST_SCHEMA;CREATE OR REPLACE FUNCTION f_my_constant() RETURNS integer LANGUAGE plpgsql as $func$ BEGIN return 100; END $func$;
quarkus.hibernate-orm.database.generation=validate

# second Agroal config
quarkus.datasource.second-datasource.db-kind=h2
quarkus.datasource.second-datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test_multiple_flyway_datasource;DB_CLOSE_DELAY=-1
quarkus.datasource.second-datasource.db-kind=postgresql

# configuration to test multiple flyway datasources
quarkus.flyway.second-datasource.locations=db/location3
quarkus.flyway.second-datasource.sql-migration-prefix=V
quarkus.flyway.second-datasource.migrate-at-start=true
quarkus.flyway.second-datasource.placeholders.mambo=poa

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
CREATE TABLE TEST_SCHEMA.quarkus_table2
(
id INT,
name VARCHAR(20)
name VARCHAR(20),
createdBy VARCHAR(100) DEFAULT CURRENT_USER NOT NULL
);
INSERT INTO TEST_SCHEMA.quarkus_table2(id, name)
VALUES (1, '1.0.1 #[title]');
VALUES (1, '1.0.1 #[title]');
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CREATE TABLE TEST_SCHEMA.quarkus
(
id INT,
name VARCHAR(20)
name VARCHAR(20),
createdBy VARCHAR(100) DEFAULT CURRENT_USER NOT NULL
);
INSERT INTO TEST_SCHEMA.quarkus(id, name)
VALUES (1, '#[foo]');
INSERT INTO TEST_SCHEMA.quarkus(id, name) VALUES (1, '#[foo]');
3 changes: 3 additions & 0 deletions integration-tests/flyway/src/main/resources/initdb.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CREATE USER scott with login password 'tiger';
GRANT ALL ON DATABASE quarkus TO scott;

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
@DisplayName("Tests flyway extension")
@DisabledOnOs(value = OS.WINDOWS, disabledReason = "Our Windows CI does not have Docker installed properly")
public class FlywayFunctionalityTest {

@Test
Expand Down Expand Up @@ -43,9 +46,10 @@ public void testPlaceholdersPrefixSuffix() {
}

@Test
@DisplayName("Returns whether the init-sql is CREATE CONSTANT IF NOT EXISTS ONE_HUNDRED VALUE 100 or not")
@DisplayName("Returns whether the init-sql is CREATE SCHEMA IF NOT EXISTS TEST_SCHEMA;CREATE OR REPLACE FUNCTION f_my_constant() RETURNS integer LANGUAGE plpgsql as $func$ BEGIN return 100; END $func$; or not")
public void testReturnInitSql() {
when().get("/flyway/init-sql").then().body(is("CREATE CONSTANT IF NOT EXISTS ONE_HUNDRED VALUE 100"));
when().get("/flyway/init-sql").then().body(is(
"CREATE SCHEMA IF NOT EXISTS TEST_SCHEMA;CREATE OR REPLACE FUNCTION f_my_constant() RETURNS integer LANGUAGE plpgsql as $func$ BEGIN return 100; END $func$;"));
}

@Test
Expand All @@ -54,4 +58,12 @@ public void testInitSqlExecuted() {
when().get("/flyway/init-sql-result").then().body(is("100"));
}

@Test
@DisplayName("Returns if the created-by user is scott")
public void testCreatedByUserIsDifferent() {
when().get("/flyway/created-by").then()
.log().ifValidationFails()
.body(is("scott"));
}

}

This file was deleted.

0 comments on commit e7d1d24

Please sign in to comment.