Skip to content

Commit

Permalink
JENKINS-23909 - Allow setting of liquibase properties file
Browse files Browse the repository at this point in the history
introduced use of properties object to do so.
  • Loading branch information
prospero238 committed Jul 21, 2014
1 parent b3a9ae4 commit 9ec1399
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 25 deletions.
18 changes: 17 additions & 1 deletion pom.xml
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.566</version>
<version>1.573</version>
</parent>

<artifactId>liquibase-runner</artifactId>
Expand Down Expand Up @@ -87,6 +87,22 @@
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>${maven-jetty-plugin.version}</version>
<configuration>
<systemProperties>
<logback.configurationFile>/home/keith/config/java/logback.xml
</logback.configurationFile>
</systemProperties>
</configuration>
</plugin>

</plugins>
</build>
</profile>
</profiles>
</project>
Expand Up @@ -37,7 +37,7 @@ public void willRun(ChangeSet changeSet,
DatabaseChangeLog databaseChangeLog,
Database database,
ChangeSet.RunStatus runStatus) {
buildListener.getLogger().println("Will run " + formatChangeset(changeSet, databaseChangeLog));


}

Expand Down
Expand Up @@ -21,7 +21,9 @@
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Properties;

import org.jenkinsci.plugins.liquibase.common.PropertiesParser;
import org.kohsuke.stapler.DataBoundConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -73,6 +75,10 @@ public class LiquibaseBuilder extends Builder {

private String databaseEngine;

private String driverName;

private String liquibasePropertiesPath;

@DataBoundConstructor
public LiquibaseBuilder(String changeLogFile,
String username,
Expand All @@ -81,7 +87,8 @@ public LiquibaseBuilder(String changeLogFile,
String defaultSchemaName,
String contexts,
String databaseEngine,
boolean testRollbacks) {
boolean testRollbacks,
String liquibasePropertiesPath) {
this.password = password;
this.defaultSchemaName = defaultSchemaName;
this.url = url;
Expand All @@ -92,28 +99,31 @@ public LiquibaseBuilder(String changeLogFile,

this.databaseEngine = databaseEngine;
this.testRollbacks = testRollbacks;
this.liquibasePropertiesPath = liquibasePropertiesPath;


}

protected static void addOptionIfPresent(ArgumentListBuilder cmdExecArgs, CliOption cliOption, String value) {
protected static void addOptionIfPresent(ArgumentListBuilder cmdExecArgs, LiquibaseProperty liquibaseProperty, String value) {
if (!Strings.isNullOrEmpty(value)) {
cmdExecArgs.add(OPTION_HYPHENS + cliOption.getCliOption(), value);
cmdExecArgs.add(OPTION_HYPHENS + liquibaseProperty.getOptionName(), value);
}
}

@Override
public boolean perform(final AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {

Properties configProperties = PropertiesParser.createConfigProperties(this);
ExecutedChangesetAction action = new ExecutedChangesetAction(build);

Liquibase liquibase = createLiquibase(build, listener, action);
Liquibase liquibase = createLiquibase(build, listener, action, configProperties);
String liqContexts = configProperties.getProperty("contexts");
try {
if (testRollbacks) {
liquibase.updateTestingRollback(contexts);
liquibase.updateTestingRollback(liqContexts);
} else {
liquibase.update(new Contexts(contexts));
liquibase.update(new Contexts(liqContexts));
}
build.addAction(action);
} catch (MigrationFailedException migrationException) {
Expand All @@ -130,37 +140,44 @@ public boolean perform(final AbstractBuild<?, ?> build, Launcher launcher, Build
e.printStackTrace(listener.getLogger());
throw new RuntimeException("Error executing liquibase liquibase database", e);
} finally {

if (liquibase.getDatabase() != null) {
try {
liquibase.getDatabase().close();
} catch (DatabaseException e) {
LOG.warn("error closing database", e);
}
}

}
return true;
}

private Liquibase createLiquibase(AbstractBuild<?, ?> build,
BuildListener listener,
ExecutedChangesetAction action) {
ExecutedChangesetAction action,
Properties configProperties) {

String driver = getDriverName();
Liquibase liquibase;
try {
Database databaseObject = CommandLineUtils
.createDatabaseObject(getClass().getClassLoader(), url, username, password, driver, null, null,
true, true, null, null, null, null);
.createDatabaseObject(getClass().getClassLoader(), configProperties.getProperty("url"),
configProperties.getProperty("username"), configProperties.getProperty("password"), driver,
configProperties.getProperty("defaultCatalogName"),
configProperties.getProperty("defaultSchemaName"), true, true, null, null, null, null);

liquibase = new Liquibase(changeLogFile, new FilePathAccessor(build), databaseObject);
liquibase = new Liquibase(configProperties.getProperty("changeLogFile"), new FilePathAccessor(build),
databaseObject);
} catch (LiquibaseException e) {
throw new RuntimeException("Error creating liquibase database.",e);
throw new RuntimeException("Error creating liquibase database.", e);
}
liquibase.setChangeExecListener(new BuildChangeExecListener(action, listener));
return liquibase;
}

public List<EmbeddedDriver> getDrivers() {
return DESCRIPTOR.getEmbeddedDrivers();
}

/**
* Reflection necessary because failedChangeset has private access on {@link liquibase.exception.MigrationFailedException}.
*
Expand All @@ -186,14 +203,18 @@ private static Optional<ChangeSet> reflectFailed(MigrationFailedException me) {

private String getDriverName() {
String driver = null;
for (EmbeddedDriver embeddedDriver : embeddedDrivers) {
if (embeddedDriver.getDisplayName().equals(databaseEngine)) {
driver = embeddedDriver.getDriverClassName();
if (LOG.isDebugEnabled()) {
LOG.debug("using db driver class[" + driver + "] ");
if (driverName == null) {
for (EmbeddedDriver embeddedDriver : embeddedDrivers) {
if (embeddedDriver.getDisplayName().equals(databaseEngine)) {
driver = embeddedDriver.getDriverClassName();
if (LOG.isDebugEnabled()) {
LOG.debug("using db driver class[" + driver + "] ");
}
break;
}
break;
}
} else {
driver = driverName;
}
return driver;
}
Expand Down Expand Up @@ -235,6 +256,42 @@ public String getDatabaseEngine() {
return databaseEngine;
}

public String getLiquibasePropertiesPath() {
return liquibasePropertiesPath;
}

public void setChangeLogFile(String changeLogFile) {
this.changeLogFile = changeLogFile;
}

public void setUsername(String username) {
this.username = username;
}

public void setPassword(String password) {
this.password = password;
}

public void setUrl(String url) {
this.url = url;
}

public void setDefaultSchemaName(String defaultSchemaName) {
this.defaultSchemaName = defaultSchemaName;
}

public void setContexts(String contexts) {
this.contexts = contexts;
}

public void setTestRollbacks(boolean testRollbacks) {
this.testRollbacks = testRollbacks;
}

public void setDriverName(String driverName) {
this.driverName = driverName;
}

public static class DescriptorImpl extends BuildStepDescriptor<Builder> {

private List<EmbeddedDriver> embeddedDrivers;
Expand Down
@@ -1,6 +1,6 @@
package org.jenkinsci.plugins.liquibase.builder;

public enum CliOption {
public enum LiquibaseProperty {
USERNAME,
PASSWORD,
DEFAULTS_FILE("defaultsFile"), CHANGELOG_FILE("changeLogFile"), CONTEXTS(), URL(), DEFAULT_SCHEMA_NAME(
Expand All @@ -9,14 +9,14 @@ public enum CliOption {

private String cliOption;

CliOption(String cliOption) {
LiquibaseProperty(String cliOption) {
this.cliOption = cliOption;
}

CliOption() {
LiquibaseProperty() {
}

public String getCliOption() {
public String getOptionName() {
String optionName;
if (cliOption == null) {
optionName = name().toLowerCase();
Expand Down
@@ -0,0 +1,79 @@
package org.jenkinsci.plugins.liquibase.common;

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import org.jenkinsci.plugins.liquibase.builder.EmbeddedDriver;
import org.jenkinsci.plugins.liquibase.builder.LiquibaseBuilder;
import org.jenkinsci.plugins.liquibase.builder.LiquibaseProperty;
import org.jenkinsci.plugins.liquibase.builder.LiquibaseRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Strings;

public class PropertiesParser {
private static final Logger LOG = LoggerFactory.getLogger(PropertiesParser.class);



/**
* Creates a properties instance representing liquibase configuration elements. Will first attempt to load
* based on {@link org.jenkinsci.plugins.liquibase.builder.LiquibaseBuilder#liquibasePropertiesPath}, then
* on any elements set directly on the builder. Therefore, those set "manually" take precedence over those
* defined in the external file.
* @param liquibaseBuilder
* @return
*/
public static Properties createConfigProperties(LiquibaseBuilder liquibaseBuilder) {
Properties properties = new Properties();

String liquibasePropertiesPath = liquibaseBuilder.getLiquibasePropertiesPath();
if (!Strings.isNullOrEmpty(liquibasePropertiesPath)) {
try {
properties.load(new FileReader(liquibasePropertiesPath));
} catch (IOException e) {
throw new LiquibaseRuntimeException(
"Unable to load properties file at[" + liquibasePropertiesPath + "] ", e);
}
}
setBasedOnConfiguration(liquibaseBuilder, properties);

return properties;
}

private static void setBasedOnConfiguration(LiquibaseBuilder liquibaseBuilder, Properties properties) {
setDriverFromDBEngine(liquibaseBuilder, properties);
setIfNotNull(properties, LiquibaseProperty.USERNAME, liquibaseBuilder.getUsername());
setIfNotNull(properties, LiquibaseProperty.DEFAULT_SCHEMA_NAME, liquibaseBuilder.getDefaultSchemaName());
setIfNotNull(properties, LiquibaseProperty.PASSWORD, liquibaseBuilder.getPassword());
setIfNotNull(properties, LiquibaseProperty.URL, liquibaseBuilder.getUrl());
setIfNotNull(properties, LiquibaseProperty.CHANGELOG_FILE, liquibaseBuilder.getChangeLogFile());
setIfNotNull(properties, LiquibaseProperty.CONTEXTS, liquibaseBuilder.getContexts());
}

private static void setIfNotNull(Properties properties,
LiquibaseProperty liquibaseProperty,
String value) {
if (!Strings.isNullOrEmpty(value)) {
properties.setProperty(liquibaseProperty.getOptionName(), value);
}

}

private static void setDriverFromDBEngine(LiquibaseBuilder liquibaseBuilder, Properties properties) {
if (!Strings.isNullOrEmpty(liquibaseBuilder.getDatabaseEngine())) {
for (EmbeddedDriver embeddedDriver : liquibaseBuilder.getDrivers()) {
if (embeddedDriver.getDisplayName().equals(liquibaseBuilder.getDatabaseEngine())) {
properties.setProperty("driver", embeddedDriver.getDriverClassName());
if (LOG.isDebugEnabled()) {
LOG.debug("using db driver class[" + embeddedDriver.getDriverClassName() + "] ");
}
break;
}
}
}
}

}
Expand Up @@ -37,6 +37,10 @@
<f:entry title="Contexts" field="contexts" description="Comma separated list of liquibase contexts to execute.">
<f:textbox value="${instance.contexts}"/>
</f:entry>
<f:entry title="Defaults file" field="liquibasePropertiesPath" description="Properties file defining liquibase configuration. You can use this instead of defining above configuration.">
<f:textbox value="${instance.liquibasePropertiesPath}"/>
</f:entry>

<f:entry title="Test Rollbacks" field="testRollbacks" description="Executes any included rollback statements in addition to the changeset.">
<f:checkbox checked="${instance.testRollbacks}"/>
</f:entry>
Expand Down

0 comments on commit 9ec1399

Please sign in to comment.