Use custom DataSource if Flyway or Liquibase has user or url
This commit enables a more flexible Liquibase/Flyway configuration by allowing for a combination of the provider's and the primary DataSource's configuration to be used. This gives developers the flexibility to specify only a user or a url and having Liquibase/Flyway fall back to individual datasource properties rather than ignoring the Liquibase/Flyway properties and falling back to the default data source. See gh-11751
This commit is contained in:
committed by
Andy Wilkinson
parent
24ec441718
commit
5d3cd23eed
@@ -39,6 +39,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
|
||||
@@ -65,6 +66,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Stephane Nicoll
|
||||
* @author Jacques-Etienne Beaudet
|
||||
* @author Eddú Meléndez
|
||||
* @author Dominic Gunn
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@Configuration
|
||||
@@ -95,6 +97,8 @@ public class FlywayAutoConfiguration {
|
||||
|
||||
private final FlywayProperties properties;
|
||||
|
||||
private final DataSourceProperties dataSourceProperties;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final DataSource dataSource;
|
||||
@@ -106,11 +110,13 @@ public class FlywayAutoConfiguration {
|
||||
private List<FlywayCallback> flywayCallbacks;
|
||||
|
||||
public FlywayConfiguration(FlywayProperties properties,
|
||||
ResourceLoader resourceLoader, ObjectProvider<DataSource> dataSource,
|
||||
DataSourceProperties dataSourceProperties, ResourceLoader resourceLoader,
|
||||
ObjectProvider<DataSource> dataSource,
|
||||
@FlywayDataSource ObjectProvider<DataSource> flywayDataSource,
|
||||
ObjectProvider<FlywayMigrationStrategy> migrationStrategy,
|
||||
ObjectProvider<List<FlywayCallback>> flywayCallbacks) {
|
||||
this.properties = properties;
|
||||
this.dataSourceProperties = dataSourceProperties;
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.dataSource = dataSource.getIfUnique();
|
||||
this.flywayDataSource = flywayDataSource.getIfAvailable();
|
||||
@@ -123,8 +129,19 @@ public class FlywayAutoConfiguration {
|
||||
public Flyway flyway() {
|
||||
Flyway flyway = new SpringBootFlyway();
|
||||
if (this.properties.isCreateDataSource()) {
|
||||
flyway.setDataSource(this.properties.getUrl(), this.properties.getUser(),
|
||||
this.properties.getPassword(),
|
||||
String url = this.properties.getUrl() == null
|
||||
? this.dataSourceProperties.getUrl()
|
||||
: this.properties.getUrl();
|
||||
|
||||
String user = this.properties.getUser() == null
|
||||
? this.dataSourceProperties.getUsername()
|
||||
: this.properties.getUser();
|
||||
|
||||
String password = this.properties.getPassword() == null
|
||||
? this.dataSourceProperties.getPassword()
|
||||
: this.properties.getPassword();
|
||||
|
||||
flyway.setDataSource(url, user, password,
|
||||
this.properties.getInitSqls().toArray(new String[0]));
|
||||
}
|
||||
else if (this.flywayDataSource != null) {
|
||||
@@ -147,9 +164,8 @@ public class FlywayAutoConfiguration {
|
||||
Assert.state(locations.length != 0,
|
||||
"Migration script locations not configured");
|
||||
boolean exists = hasAtLeastOneLocation(locations);
|
||||
Assert.state(exists,
|
||||
() -> "Cannot find migrations location in: " + Arrays.asList(
|
||||
locations)
|
||||
Assert.state(exists, () -> "Cannot find migrations location in: "
|
||||
+ Arrays.asList(locations)
|
||||
+ " (please add migrations or check your Flyway configuration)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ public class FlywayProperties {
|
||||
}
|
||||
|
||||
public boolean isCreateDataSource() {
|
||||
return this.url != null && this.user != null;
|
||||
return this.url != null || this.user != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
@@ -58,6 +59,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Phillip Webb
|
||||
* @author Eddú Meléndez
|
||||
* @author Andy Wilkinson
|
||||
* @author Dominic Gunn
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@Configuration
|
||||
@@ -83,6 +85,8 @@ public class LiquibaseAutoConfiguration {
|
||||
|
||||
private final LiquibaseProperties properties;
|
||||
|
||||
private final DataSourceProperties dataSourceProperties;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final DataSource dataSource;
|
||||
@@ -90,9 +94,11 @@ public class LiquibaseAutoConfiguration {
|
||||
private final DataSource liquibaseDataSource;
|
||||
|
||||
public LiquibaseConfiguration(LiquibaseProperties properties,
|
||||
ResourceLoader resourceLoader, ObjectProvider<DataSource> dataSource,
|
||||
DataSourceProperties dataSourceProperties, ResourceLoader resourceLoader,
|
||||
ObjectProvider<DataSource> dataSource,
|
||||
@LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource) {
|
||||
this.properties = properties;
|
||||
this.dataSourceProperties = dataSourceProperties;
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.dataSource = dataSource.getIfUnique();
|
||||
this.liquibaseDataSource = liquibaseDataSource.getIfAvailable();
|
||||
@@ -140,16 +146,27 @@ public class LiquibaseAutoConfiguration {
|
||||
if (this.liquibaseDataSource != null) {
|
||||
return this.liquibaseDataSource;
|
||||
}
|
||||
if (this.properties.getUrl() == null) {
|
||||
if (this.properties.getUrl() == null && this.properties.getUser() == null) {
|
||||
return this.dataSource;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private DataSource createNewDataSource() {
|
||||
return DataSourceBuilder.create().url(this.properties.getUrl())
|
||||
.username(this.properties.getUser())
|
||||
.password(this.properties.getPassword()).build();
|
||||
String url = this.properties.getUrl() == null
|
||||
? this.dataSourceProperties.getUrl()
|
||||
: this.properties.getUrl();
|
||||
|
||||
String user = this.properties.getUser() == null
|
||||
? this.dataSourceProperties.getUsername()
|
||||
: this.properties.getUser();
|
||||
|
||||
String password = this.properties.getPassword() == null
|
||||
? this.dataSourceProperties.getPassword()
|
||||
: this.properties.getPassword();
|
||||
|
||||
return DataSourceBuilder.create().url(url).username(user).password(password)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ import static org.mockito.Mockito.mock;
|
||||
* @author Vedran Pavic
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Dominic Gunn
|
||||
*/
|
||||
public class FlywayAutoConfigurationTests {
|
||||
|
||||
@@ -74,9 +75,19 @@ public class FlywayAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDataSource() {
|
||||
public void createDataSourceWithUrl() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
.withPropertyValues("spring.flyway.url:jdbc:hsqldb:mem:flywaytest",
|
||||
.withPropertyValues("spring.flyway.url:jdbc:hsqldb:mem:flywaytest")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(Flyway.class);
|
||||
assertThat(context.getBean(Flyway.class).getDataSource()).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDataSourceWithUser() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
.withPropertyValues("spring.datasource.url:jdbc:hsqldb:mem:normal",
|
||||
"spring.flyway.user:sa")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(Flyway.class);
|
||||
|
||||
@@ -58,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Eddú Meléndez
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @author Dominic Gunn
|
||||
*/
|
||||
public class LiquibaseAutoConfigurationTests {
|
||||
|
||||
@@ -153,8 +154,7 @@ public class LiquibaseAutoConfigurationTests {
|
||||
@Test
|
||||
public void overrideDataSource() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
.withPropertyValues("spring.liquibase.url:jdbc:hsqldb:mem:liquibase",
|
||||
"spring.liquibase.user:sa")
|
||||
.withPropertyValues("spring.liquibase.url:jdbc:hsqldb:mem:liquibase")
|
||||
.run(assertLiquibase((liquibase) -> {
|
||||
DataSource dataSource = liquibase.getDataSource();
|
||||
assertThat(((HikariDataSource) dataSource).isClosed()).isTrue();
|
||||
@@ -163,6 +163,21 @@ public class LiquibaseAutoConfigurationTests {
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overrideUser() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
.withPropertyValues("spring.datasource.url:jdbc:hsqldb:mem:normal",
|
||||
"spring.datasource.username:not-sa", "spring.liquibase.user:sa")
|
||||
.run(assertLiquibase((liquibase) -> {
|
||||
DataSource dataSource = liquibase.getDataSource();
|
||||
assertThat(((HikariDataSource) dataSource).isClosed()).isTrue();
|
||||
assertThat(((HikariDataSource) dataSource).getJdbcUrl())
|
||||
.isEqualTo("jdbc:hsqldb:mem:normal");
|
||||
assertThat(((HikariDataSource) dataSource).getUsername())
|
||||
.isEqualTo("sa");
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeLogDoesNotExist() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
|
||||
Reference in New Issue
Block a user