|
|
@ -16,13 +16,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.boot.actuate.endpoint;
|
|
|
|
package org.springframework.boot.actuate.endpoint;
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Collections;
|
|
|
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
import javax.sql.DataSource;
|
|
|
|
import javax.sql.DataSource;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import liquibase.changelog.ChangeLogHistoryService;
|
|
|
|
|
|
|
|
import liquibase.changelog.ChangeSet.ExecType;
|
|
|
|
|
|
|
|
import liquibase.changelog.RanChangeSet;
|
|
|
|
import liquibase.changelog.StandardChangeLogHistoryService;
|
|
|
|
import liquibase.changelog.StandardChangeLogHistoryService;
|
|
|
|
import liquibase.database.Database;
|
|
|
|
import liquibase.database.Database;
|
|
|
|
import liquibase.database.DatabaseFactory;
|
|
|
|
import liquibase.database.DatabaseFactory;
|
|
|
@ -41,7 +47,7 @@ import org.springframework.util.StringUtils;
|
|
|
|
* @since 1.3.0
|
|
|
|
* @since 1.3.0
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@ConfigurationProperties(prefix = "endpoints.liquibase")
|
|
|
|
@ConfigurationProperties(prefix = "endpoints.liquibase")
|
|
|
|
public class LiquibaseEndpoint extends AbstractEndpoint<List<LiquibaseReport>> {
|
|
|
|
public class LiquibaseEndpoint extends AbstractEndpoint<Map<String, LiquibaseReport>> {
|
|
|
|
|
|
|
|
|
|
|
|
private final Map<String, SpringLiquibase> liquibases;
|
|
|
|
private final Map<String, SpringLiquibase> liquibases;
|
|
|
|
|
|
|
|
|
|
|
@ -56,57 +62,173 @@ public class LiquibaseEndpoint extends AbstractEndpoint<List<LiquibaseReport>> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public List<LiquibaseReport> invoke() {
|
|
|
|
public Map<String, LiquibaseReport> invoke() {
|
|
|
|
List<LiquibaseReport> reports = new ArrayList<>();
|
|
|
|
Map<String, LiquibaseReport> reports = new HashMap<>();
|
|
|
|
DatabaseFactory factory = DatabaseFactory.getInstance();
|
|
|
|
DatabaseFactory factory = DatabaseFactory.getInstance();
|
|
|
|
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
|
|
|
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
|
|
|
for (Map.Entry<String, SpringLiquibase> entry : this.liquibases.entrySet()) {
|
|
|
|
for (Map.Entry<String, SpringLiquibase> entry : this.liquibases.entrySet()) {
|
|
|
|
|
|
|
|
reports.put(entry.getKey(), createReport(entry.getValue(), service, factory));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return reports;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private LiquibaseReport createReport(SpringLiquibase liquibase,
|
|
|
|
|
|
|
|
ChangeLogHistoryService service, DatabaseFactory factory) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
DataSource dataSource = entry.getValue().getDataSource();
|
|
|
|
DataSource dataSource = liquibase.getDataSource();
|
|
|
|
JdbcConnection connection = new JdbcConnection(
|
|
|
|
JdbcConnection connection = new JdbcConnection(dataSource.getConnection());
|
|
|
|
dataSource.getConnection());
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
Database database = factory
|
|
|
|
Database database = factory.findCorrectDatabaseImplementation(connection);
|
|
|
|
.findCorrectDatabaseImplementation(connection);
|
|
|
|
String defaultSchema = liquibase.getDefaultSchema();
|
|
|
|
String defaultSchema = entry.getValue().getDefaultSchema();
|
|
|
|
|
|
|
|
if (StringUtils.hasText(defaultSchema)) {
|
|
|
|
if (StringUtils.hasText(defaultSchema)) {
|
|
|
|
database.setDefaultSchemaName(defaultSchema);
|
|
|
|
database.setDefaultSchemaName(defaultSchema);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reports.add(new LiquibaseReport(entry.getKey(),
|
|
|
|
service.setDatabase(database);
|
|
|
|
service.queryDatabaseChangeLogTable(database)));
|
|
|
|
return new LiquibaseReport(service.getRanChangeSets().stream()
|
|
|
|
|
|
|
|
.map(ChangeSet::new).collect(Collectors.toList()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
finally {
|
|
|
|
connection.close();
|
|
|
|
connection.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex) {
|
|
|
|
catch (Exception ex) {
|
|
|
|
throw new IllegalStateException("Unable to get Liquibase changelog", ex);
|
|
|
|
throw new IllegalStateException("Unable to get Liquibase change sets", ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return reports;
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Report for a single {@link SpringLiquibase} instance.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public static class LiquibaseReport {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final List<ChangeSet> changeSets;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public LiquibaseReport(List<ChangeSet> changeSets) {
|
|
|
|
|
|
|
|
this.changeSets = changeSets;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<ChangeSet> getChangeSets() {
|
|
|
|
|
|
|
|
return this.changeSets;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Liquibase report for one datasource.
|
|
|
|
* A Liquibase change set.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public static class LiquibaseReport {
|
|
|
|
public static class ChangeSet {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String author;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String changeLog;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String comments;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final ContextExpression contextExpression;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Date dateExecuted;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String deploymentId;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String description;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final ExecType execType;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String id;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Set<String> labels;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String checksum;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Integer orderExecuted;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String tag;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ChangeSet(RanChangeSet ranChangeSet) {
|
|
|
|
|
|
|
|
this.author = ranChangeSet.getAuthor();
|
|
|
|
|
|
|
|
this.changeLog = ranChangeSet.getChangeLog();
|
|
|
|
|
|
|
|
this.comments = ranChangeSet.getComments();
|
|
|
|
|
|
|
|
this.contextExpression = new ContextExpression(
|
|
|
|
|
|
|
|
ranChangeSet.getContextExpression().getContexts());
|
|
|
|
|
|
|
|
this.dateExecuted = ranChangeSet.getDateExecuted();
|
|
|
|
|
|
|
|
this.deploymentId = ranChangeSet.getDeploymentId();
|
|
|
|
|
|
|
|
this.description = ranChangeSet.getDescription();
|
|
|
|
|
|
|
|
this.execType = ranChangeSet.getExecType();
|
|
|
|
|
|
|
|
this.id = ranChangeSet.getId();
|
|
|
|
|
|
|
|
this.labels = ranChangeSet.getLabels().getLabels();
|
|
|
|
|
|
|
|
this.checksum = ranChangeSet.getLastCheckSum() == null ? null
|
|
|
|
|
|
|
|
: ranChangeSet.getLastCheckSum().toString();
|
|
|
|
|
|
|
|
this.orderExecuted = ranChangeSet.getOrderExecuted();
|
|
|
|
|
|
|
|
this.tag = ranChangeSet.getTag();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getAuthor() {
|
|
|
|
|
|
|
|
return this.author;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getChangeLog() {
|
|
|
|
|
|
|
|
return this.changeLog;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getComments() {
|
|
|
|
|
|
|
|
return this.comments;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private final String name;
|
|
|
|
public ContextExpression getContextExpression() {
|
|
|
|
|
|
|
|
return this.contextExpression;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private final List<Map<String, ?>> changeLogs;
|
|
|
|
public Date getDateExecuted() {
|
|
|
|
|
|
|
|
return this.dateExecuted;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getDeploymentId() {
|
|
|
|
|
|
|
|
return this.deploymentId;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getDescription() {
|
|
|
|
|
|
|
|
return this.description;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ExecType getExecType() {
|
|
|
|
|
|
|
|
return this.execType;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public LiquibaseReport(String name, List<Map<String, ?>> changeLogs) {
|
|
|
|
public String getId() {
|
|
|
|
this.name = name;
|
|
|
|
return this.id;
|
|
|
|
this.changeLogs = changeLogs;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public String getName() {
|
|
|
|
public Set<String> getLabels() {
|
|
|
|
return this.name;
|
|
|
|
return this.labels;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getChecksum() {
|
|
|
|
|
|
|
|
return this.checksum;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Integer getOrderExecuted() {
|
|
|
|
|
|
|
|
return this.orderExecuted;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getTag() {
|
|
|
|
|
|
|
|
return this.tag;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* A context expression in a {@link ChangeSet}.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public static class ContextExpression {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Set<String> contexts;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ContextExpression(Set<String> contexts) {
|
|
|
|
|
|
|
|
this.contexts = contexts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<Map<String, ?>> getChangeLogs() {
|
|
|
|
public Set<String> getContexts() {
|
|
|
|
return this.changeLogs;
|
|
|
|
return this.contexts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|