diff --git a/cassandra-migration-spring-boot-starter/pom.xml b/cassandra-migration-spring-boot-starter/pom.xml
index 2b712c2..b0cdd23 100644
--- a/cassandra-migration-spring-boot-starter/pom.xml
+++ b/cassandra-migration-spring-boot-starter/pom.xml
@@ -61,6 +61,12 @@
${spring.boot.version}
provided
+
+ org.springframework.boot
+ spring-boot-actuator
+ ${spring.boot.version}
+ provided
+
org.springframework.boot
spring-boot-test-autoconfigure
diff --git a/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfiguration.java b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfiguration.java
index 9305ae1..8ed59ce 100644
--- a/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfiguration.java
+++ b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationAutoConfiguration.java
@@ -1,15 +1,19 @@
package org.cognitor.cassandra.migration.spring;
import com.datastax.driver.core.Cluster;
+import org.cognitor.cassandra.migration.Database;
import org.cognitor.cassandra.migration.MigrationRepository;
import org.cognitor.cassandra.migration.collector.FailOnDuplicatesCollector;
import org.cognitor.cassandra.migration.collector.IgnoreDuplicatesCollector;
import org.cognitor.cassandra.migration.keyspace.KeyspaceDefinition;
import org.cognitor.cassandra.migration.scanner.ScannerRegistry;
+import org.cognitor.cassandra.migration.spring.health.MigrationStatus;
import org.cognitor.cassandra.migration.spring.scanner.SpringBootLocationScanner;
import org.cognitor.cassandra.migration.tasks.TaskChain;
import org.cognitor.cassandra.migration.tasks.TaskChainBuilder;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -28,36 +32,60 @@
@ConditionalOnClass(Cluster.class)
public class CassandraMigrationAutoConfiguration {
private final CassandraMigrationConfigurationProperties properties;
+ private final Cluster cluster;
@Autowired
- public CassandraMigrationAutoConfiguration(CassandraMigrationConfigurationProperties properties) {
+ public CassandraMigrationAutoConfiguration(CassandraMigrationConfigurationProperties properties, Cluster cluster) {
this.properties = properties;
+ this.cluster = cluster;
}
-
- @Bean
+ @Bean(initMethod = "execute")
@ConditionalOnBean(Cluster.class)
@ConditionalOnMissingBean(TaskChain.class)
- public TaskChain migrationProcess(Cluster cluster) {
+ public TaskChain migrationProcess() {
+ if (properties.isEnabled()) {
+ return createMigrationTaskChain();
+ } else {
+ return createEmptyTaskChain();
+ }
+ }
+
+ private TaskChain createEmptyTaskChain() {
+ return new TaskChain();
+ }
+
+ private TaskChain createMigrationTaskChain() {
+ return new TaskChainBuilder(cluster,
+ migrationConfiguration(),
+ migrationRepository())
+ .buildTaskChain(migrationDatabase());
+ }
+
+ @Bean
+ org.cognitor.cassandra.migration.Configuration migrationConfiguration() {
if (!properties.hasKeyspaceName()) {
throw new IllegalStateException("Please specify ['cassandra.migration.keyspace-name'] in" +
" order to migrate your database");
}
KeyspaceDefinition keyspaceDefinition = new KeyspaceDefinition(properties.getKeyspaceName())
.with(properties.getReplicationStrategy());
- return new TaskChainBuilder(cluster,
- new org.cognitor.cassandra.migration.Configuration(keyspaceDefinition)
- .setChecksumValidation(properties.isChecksumValidation())
+ return new org.cognitor.cassandra.migration.Configuration(keyspaceDefinition).setChecksumValidation(properties.isChecksumValidation())
.setValidateOnly(properties.isChecksumValidationOnly())
.setRecalculateChecksum(properties.isRecalculateChecksum())
.setRecalculateChecksumOnly(properties.isRecalculateChecksumOnly())
.setConsistencyLevel(properties.getConsistencyLevel())
- .setCreateKeyspace(properties.isCreateKeyspace()),
- createRepository())
- .buildTaskChain();
+ .setCreateKeyspace(properties.isCreateKeyspace());
+ }
+
+ @Bean
+ Database migrationDatabase(){
+ return new Database(cluster, migrationConfiguration());
}
- private MigrationRepository createRepository() {
+ @ConditionalOnMissingBean(MigrationRepository.class)
+ @Bean
+ MigrationRepository migrationRepository() {
ScannerRegistry registry = new ScannerRegistry();
registry.register(ScannerRegistry.JAR_SCHEME, new SpringBootLocationScanner());
if (properties.getStrategy() == ScriptCollectorStrategy.FAIL_ON_DUPLICATES) {
@@ -65,4 +93,10 @@ private MigrationRepository createRepository() {
}
return new MigrationRepository(properties.getScriptLocation(), new IgnoreDuplicatesCollector(), registry);
}
+
+ @ConditionalOnClass(HealthIndicator.class)
+ @Bean
+ MigrationStatus migrationStatus() {
+ return new MigrationStatus(migrationRepository(), migrationDatabase());
+ }
}
diff --git a/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationProperties.java b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationProperties.java
index e0b24e5..6151a4a 100644
--- a/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationProperties.java
+++ b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationProperties.java
@@ -17,6 +17,7 @@
*/
@ConfigurationProperties(prefix = "cassandra.migration")
public class CassandraMigrationConfigurationProperties {
+ private boolean enabled = true;
private ScriptCollectorStrategy strategy = ScriptCollectorStrategy.FAIL_ON_DUPLICATES;
private String scriptLocation = MigrationRepository.DEFAULT_SCRIPT_PATH;
private String keyspaceName;
@@ -29,6 +30,14 @@ public class CassandraMigrationConfigurationProperties {
private boolean recalculateChecksum = false;
private ConsistencyLevel consistencyLevel = ConsistencyLevel.QUORUM;
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
/**
* @return The location of the migration scripts. Never null.
*/
diff --git a/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/annotation/AfterMigration.java b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/annotation/AfterMigration.java
new file mode 100644
index 0000000..e77d058
--- /dev/null
+++ b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/annotation/AfterMigration.java
@@ -0,0 +1,14 @@
+package org.cognitor.cassandra.migration.spring.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.context.annotation.DependsOn;
+
+@DependsOn("migrationProcess")
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface AfterMigration {
+}
diff --git a/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/health/MigrationStatus.java b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/health/MigrationStatus.java
new file mode 100644
index 0000000..9f4946d
--- /dev/null
+++ b/cassandra-migration-spring-boot-starter/src/main/java/org/cognitor/cassandra/migration/spring/health/MigrationStatus.java
@@ -0,0 +1,42 @@
+package org.cognitor.cassandra.migration.spring.health;
+
+import org.cognitor.cassandra.migration.Database;
+import org.cognitor.cassandra.migration.MigrationRepository;
+import org.cognitor.cassandra.migration.spring.CassandraMigrationConfigurationProperties;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@EnableConfigurationProperties(CassandraMigrationConfigurationProperties.class)
+public class MigrationStatus implements HealthIndicator {
+
+ private final MigrationRepository migrationRepository;
+ private final Database migrationDatabase;
+
+ public MigrationStatus(MigrationRepository migrationRepository, Database database) {
+ this.migrationRepository = migrationRepository;
+ this.migrationDatabase = database;
+ }
+
+ @Override
+ public Health health() {
+ try {
+ int latestVersion = migrationRepository.getLatestVersion();
+ final int dbVersion = migrationDatabase.getVersion();
+
+ if(latestVersion != dbVersion) {
+ return Health.unknown()
+ .withDetail("databaseVersion", dbVersion)
+ .withDetail("sourceVersion", latestVersion)
+ .build();
+ } else {
+ return Health.up()
+ .withDetail("databaseVersion", dbVersion)
+ .withDetail("sourceVersion", latestVersion)
+ .build();
+ }
+ } catch (Throwable ex) {
+ return Health.unknown().withException(ex).build();
+ }
+ }
+}
diff --git a/cassandra-migration-spring-boot-starter/src/test/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationPropertiesTest.java b/cassandra-migration-spring-boot-starter/src/test/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationPropertiesTest.java
index 36f4d8e..98b07b7 100644
--- a/cassandra-migration-spring-boot-starter/src/test/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationPropertiesTest.java
+++ b/cassandra-migration-spring-boot-starter/src/test/java/org/cognitor/cassandra/migration/spring/CassandraMigrationConfigurationPropertiesTest.java
@@ -2,7 +2,9 @@
import com.datastax.driver.core.ConsistencyLevel;
import org.junit.Test;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Configuration;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.core.Is.is;
@@ -30,7 +32,7 @@ public void shouldPopulatePropertiesWhenPropertiesFileGiven() {
addEnvironment(context, "cassandra.migration.network-strategy.data-centers.boston=3");
addEnvironment(context, "cassandra.migration.network-strategy.data-centers.seattle=2");
addEnvironment(context, "cassandra.migration.network-strategy.data-centers.tokyo=2");
- context.register(CassandraMigrationAutoConfiguration.class);
+ context.register(PropertiesTestConfiguration.class);
context.refresh();
CassandraMigrationConfigurationProperties properties =
context.getBean(CassandraMigrationConfigurationProperties.class);
@@ -49,7 +51,7 @@ public void shouldPopulatePropertiesWhenPropertiesFileGiven() {
public void shouldReturnDefaultValuesWhenNoOptionalPropertiesGiven() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
- context.register(CassandraMigrationAutoConfiguration.class);
+ context.register(PropertiesTestConfiguration.class);
context.refresh();
CassandraMigrationConfigurationProperties properties =
context.getBean(CassandraMigrationConfigurationProperties.class);
@@ -57,4 +59,15 @@ public void shouldReturnDefaultValuesWhenNoOptionalPropertiesGiven() {
assertThat(properties.getScriptLocation(), is(equalTo("cassandra/migration")));
assertThat(properties.getStrategy(), is(equalTo(ScriptCollectorStrategy.FAIL_ON_DUPLICATES)));
}
-}
\ No newline at end of file
+
+ @Configuration
+ @EnableConfigurationProperties({CassandraMigrationConfigurationProperties.class})
+ static class PropertiesTestConfiguration {
+ private final CassandraMigrationConfigurationProperties properties;
+
+ public PropertiesTestConfiguration(CassandraMigrationConfigurationProperties properties) {
+ this.properties = properties;
+ }
+ }
+
+}
diff --git a/cassandra-migration/src/main/java/org/cognitor/cassandra/migration/tasks/TaskChainBuilder.java b/cassandra-migration/src/main/java/org/cognitor/cassandra/migration/tasks/TaskChainBuilder.java
index 8cc4870..cda1f7a 100644
--- a/cassandra-migration/src/main/java/org/cognitor/cassandra/migration/tasks/TaskChainBuilder.java
+++ b/cassandra-migration/src/main/java/org/cognitor/cassandra/migration/tasks/TaskChainBuilder.java
@@ -32,6 +32,10 @@ public TaskChainBuilder(Cluster cluster, Configuration configuration, MigrationR
public TaskChain buildTaskChain() {
Database database = new Database(cluster, configuration);
+ return buildTaskChain(database);
+ }
+
+ public TaskChain buildTaskChain(Database database) {
TaskChain chain = new TaskChain();
if (configuration.isRecalculateChecksumOnly()) {
return chain.addTask(new RecalculateChecksumTask(database, migrationRepository));