Add support for multiple beans in the Flyway and Liquibase endpoints
Closes gh-6610 See gh-6613
This commit is contained in:
parent
eb294956d8
commit
53d25999f3
|
|
@ -55,7 +55,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionEvaluationRepor
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
|
|
@ -188,26 +187,26 @@ public class EndpointAutoConfiguration {
|
|||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnSingleCandidate(Flyway.class)
|
||||
@ConditionalOnBean(Flyway.class)
|
||||
@ConditionalOnClass(Flyway.class)
|
||||
static class FlywayEndpointConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FlywayEndpoint flywayEndpoint(Flyway flyway) {
|
||||
public FlywayEndpoint flywayEndpoint(List<Flyway> flyway) {
|
||||
return new FlywayEndpoint(flyway);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnSingleCandidate(SpringLiquibase.class)
|
||||
@ConditionalOnBean(SpringLiquibase.class)
|
||||
@ConditionalOnClass(SpringLiquibase.class)
|
||||
static class LiquibaseEndpointConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public LiquibaseEndpoint liquibaseEndpoint(SpringLiquibase liquibase) {
|
||||
public LiquibaseEndpoint liquibaseEndpoint(List<SpringLiquibase> liquibase) {
|
||||
return new LiquibaseEndpoint(liquibase);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,15 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.flywaydb.core.api.MigrationInfo;
|
||||
|
|
@ -38,21 +44,46 @@ import org.springframework.util.Assert;
|
|||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.flyway")
|
||||
public class FlywayEndpoint extends AbstractEndpoint<List<FlywayMigration>> {
|
||||
public class FlywayEndpoint extends AbstractEndpoint<Map<String, List<FlywayMigration>>> {
|
||||
|
||||
private final Flyway flyway;
|
||||
private final List<Flyway> flyway;
|
||||
|
||||
public FlywayEndpoint(Flyway flyway) {
|
||||
this(Collections.singletonList(flyway));
|
||||
}
|
||||
|
||||
public FlywayEndpoint(List<Flyway> flyway) {
|
||||
super("flyway");
|
||||
Assert.notNull(flyway, "Flyway must not be null");
|
||||
this.flyway = flyway;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlywayMigration> invoke() {
|
||||
List<FlywayMigration> migrations = new ArrayList<FlywayMigration>();
|
||||
for (MigrationInfo info : this.flyway.info().all()) {
|
||||
migrations.add(new FlywayMigration(info));
|
||||
public Map<String, List<FlywayMigration>> invoke() {
|
||||
Map<String, List<FlywayMigration>> migrations = new HashMap<String, List<FlywayMigration>>();
|
||||
for (Flyway flyway : this.flyway) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = flyway.getDataSource().getConnection();
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
List<FlywayMigration> migration = new ArrayList<FlywayMigration>();
|
||||
for (MigrationInfo info : flyway.info().all()) {
|
||||
migration.add(new FlywayMigration(info));
|
||||
}
|
||||
migrations.put(metaData.getURL(), migration);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
//Continue
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
//Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return migrations;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -25,6 +29,7 @@ import liquibase.changelog.StandardChangeLogHistoryService;
|
|||
import liquibase.database.Database;
|
||||
import liquibase.database.DatabaseFactory;
|
||||
import liquibase.database.jvm.JdbcConnection;
|
||||
import liquibase.exception.DatabaseException;
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
|
@ -37,34 +42,50 @@ import org.springframework.util.Assert;
|
|||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.liquibase")
|
||||
public class LiquibaseEndpoint extends AbstractEndpoint<List<Map<String, ?>>> {
|
||||
public class LiquibaseEndpoint extends AbstractEndpoint<Map<String, List<Map<String, ?>>>> {
|
||||
|
||||
private final SpringLiquibase liquibase;
|
||||
private final List<SpringLiquibase> liquibase;
|
||||
|
||||
public LiquibaseEndpoint(SpringLiquibase liquibase) {
|
||||
this(Collections.singletonList(liquibase));
|
||||
}
|
||||
|
||||
public LiquibaseEndpoint(List<SpringLiquibase> liquibase) {
|
||||
super("liquibase");
|
||||
Assert.notNull(liquibase, "Liquibase must not be null");
|
||||
this.liquibase = liquibase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, ?>> invoke() {
|
||||
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
||||
try {
|
||||
DatabaseFactory factory = DatabaseFactory.getInstance();
|
||||
DataSource dataSource = this.liquibase.getDataSource();
|
||||
JdbcConnection connection = new JdbcConnection(dataSource.getConnection());
|
||||
public Map<String, List<Map<String, ?>>> invoke() {
|
||||
Map<String, List<Map<String, ?>>> services = new HashMap<String, List<Map<String, ?>>>();
|
||||
|
||||
DatabaseFactory factory = DatabaseFactory.getInstance();
|
||||
|
||||
for (SpringLiquibase liquibase : this.liquibase) {
|
||||
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
||||
try {
|
||||
Database database = factory.findCorrectDatabaseImplementation(connection);
|
||||
return service.queryDatabaseChangeLogTable(database);
|
||||
DatabaseMetaData metaData = liquibase.getDataSource().getConnection().getMetaData();
|
||||
try {
|
||||
DataSource dataSource = liquibase.getDataSource();
|
||||
JdbcConnection connection = new JdbcConnection(dataSource.getConnection());
|
||||
try {
|
||||
Database database = factory.findCorrectDatabaseImplementation(connection);
|
||||
services.put(metaData.getURL(), service.queryDatabaseChangeLogTable(database));
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
catch (DatabaseException ex) {
|
||||
throw new IllegalStateException("Unable to get Liquibase changelog", ex);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
catch (SQLException e) {
|
||||
//Continue
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to get Liquibase changelog", ex);
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import java.util.LinkedHashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.junit.After;
|
||||
|
|
@ -50,6 +52,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionEvaluationRepor
|
|||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.info.ProjectInfoProperties;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.boot.bind.PropertySourcesBinder;
|
||||
|
|
@ -65,7 +68,6 @@ import org.springframework.core.io.support.PropertiesLoaderUtils;
|
|||
import org.springframework.validation.BindException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link EndpointAutoConfiguration}.
|
||||
|
|
@ -222,12 +224,13 @@ public class EndpointAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void flywayEndpointIsDisabledWhenThereAreMultipleFlywayBeans() {
|
||||
public void testFlywayEndpointWithMultipleFlywayBeans() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(MultipleFlywayBeansConfig.class,
|
||||
EndpointAutoConfiguration.class);
|
||||
FlywayAutoConfiguration.class, EndpointAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBeansOfType(FlywayEndpoint.class)).hasSize(0);
|
||||
assertThat(this.context.getBeansOfType(Flyway.class)).hasSize(2);
|
||||
assertThat(this.context.getBeansOfType(FlywayEndpoint.class)).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -242,12 +245,13 @@ public class EndpointAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void liquibaseEndpointIsDisabledWhenThereAreMultipleSpringLiquibaseBeans() {
|
||||
public void testLiquibaseEndpointWithMultipleSpringLiquibaseBeans() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(MultipleLiquibaseBeansConfig.class,
|
||||
EndpointAutoConfiguration.class);
|
||||
LiquibaseAutoConfiguration.class, EndpointAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBeansOfType(LiquibaseEndpoint.class)).hasSize(0);
|
||||
assertThat(this.context.getBeansOfType(SpringLiquibase.class)).hasSize(2);
|
||||
assertThat(this.context.getBeansOfType(LiquibaseEndpoint.class)).hasSize(1);
|
||||
}
|
||||
|
||||
private void load(Class<?>... config) {
|
||||
|
|
@ -330,32 +334,58 @@ public class EndpointAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class MultipleFlywayBeansConfig {
|
||||
static class DataSourceConfig {
|
||||
|
||||
@Bean
|
||||
Flyway flywayOne() {
|
||||
return mock(Flyway.class);
|
||||
public DataSource dataSourceOne() {
|
||||
return DataSourceBuilder.create().url("jdbc:hsqldb:mem:changelogdbtest")
|
||||
.username("sa").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Flyway flywayTwo() {
|
||||
return mock(Flyway.class);
|
||||
public DataSource dataSourceTwo() {
|
||||
return DataSourceBuilder.create().url("jdbc:hsqldb:mem:changelogdbtest2")
|
||||
.username("sa").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class MultipleLiquibaseBeansConfig {
|
||||
static class MultipleFlywayBeansConfig extends DataSourceConfig {
|
||||
|
||||
@Bean
|
||||
SpringLiquibase liquibaseOne() {
|
||||
return mock(SpringLiquibase.class);
|
||||
public Flyway flywayOne() {
|
||||
Flyway flyway = new Flyway();
|
||||
flyway.setDataSource(dataSourceOne());
|
||||
return flyway;
|
||||
}
|
||||
|
||||
@Bean
|
||||
SpringLiquibase liquibaseTwo() {
|
||||
return mock(SpringLiquibase.class);
|
||||
public Flyway flywayTwo() {
|
||||
Flyway flyway = new Flyway();
|
||||
flyway.setDataSource(dataSourceTwo());
|
||||
return flyway;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class MultipleLiquibaseBeansConfig extends DataSourceConfig {
|
||||
|
||||
@Bean
|
||||
public SpringLiquibase liquibaseOne() {
|
||||
SpringLiquibase liquibase = new SpringLiquibase();
|
||||
liquibase.setChangeLog("classpath:/db/changelog/db.changelog-master.yaml");
|
||||
liquibase.setDataSource(dataSourceOne());
|
||||
return liquibase;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringLiquibase liquibaseTwo() {
|
||||
SpringLiquibase liquibase = new SpringLiquibase();
|
||||
liquibase.setChangeLog("classpath:/db/changelog/db.changelog-master.yaml");
|
||||
liquibase.setDataSource(dataSourceTwo());
|
||||
return liquibase;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue