Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DAT 3917 #1000

Merged
merged 22 commits into from Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
85df01f
WIP
wwillard7800 Feb 5, 2020
3fe0866
Merge remote-tracking branch 'origin/DAT-3849' into DAT-3917
wwillard7800 Feb 5, 2020
7094d4e
Happy path rollback for an update (deployment ID) working for DAT-3917
wwillard7800 Feb 6, 2020
41f8064
Merge remote-tracking branch 'origin/DAT-3849' into DAT-3917
wwillard7800 Feb 6, 2020
ca2e488
Merge remote-tracking branch 'origin/DAT-3849' into DAT-3917
wwillard7800 Feb 6, 2020
0085ca2
Implementation of targeted update rollback DAT-3917
wwillard7800 Feb 11, 2020
2d3d546
Merge remote-tracking branch 'origin/3.8.x' into DAT-3917
wwillard7800 Feb 11, 2020
a6c5b76
Implemented rollbackOneUpdate DAT-3916
wwillard7800 Feb 13, 2020
e82e773
Modifications for PR and help
wwillard7800 Feb 14, 2020
05db40c
Global help changes
wwillard7800 Feb 17, 2020
8e14e58
Doc changes
wwillard7800 Feb 17, 2020
c61e5f6
Re-add code for Pro license check which should not have been removed
wwillard7800 Feb 17, 2020
6d2344a
Do not require --force for rollbackOneUpdateSQL
wwillard7800 Feb 18, 2020
5904f92
Merge remote-tracking branch 'origin/3.8.x' into DAT-3917
wwillard7800 Feb 18, 2020
fdf5c94
Turn down the log level of the Pro license check
wwillard7800 Feb 18, 2020
2689b3b
Re-worked last change for non-pro commands
wwillard7800 Feb 18, 2020
bb590b0
Moved Pro license check to after properties are ready
wwillard7800 Feb 18, 2020
cfc4166
Do not close Writer if stdout
wwillard7800 Feb 19, 2020
5633502
Use correct command name in license check message
wwillard7800 Feb 19, 2020
d5d3bd5
Modified global help for history command
wwillard7800 Feb 20, 2020
8bc98d9
Remove curly quotes from help text
wwillard7800 Feb 20, 2020
ce3f63e
Update docs
wwillard7800 Feb 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion liquibase-core/src/main/java/liquibase/change/Change.java
Expand Up @@ -100,7 +100,7 @@ public interface Change extends LiquibaseSerializable {


/**
* Returns true if this change be rolled back for the given database.
* Returns true if this can change be rolled back for the given database.
*/
public boolean supportsRollback(Database database);

Expand Down
Expand Up @@ -12,8 +12,6 @@
import liquibase.database.DatabaseList;
import liquibase.database.ObjectQuotingStrategy;
import liquibase.exception.*;
import liquibase.logging.LogFactory;
import liquibase.exception.*;
import liquibase.logging.LogService;
import liquibase.logging.LogType;
import liquibase.logging.Logger;
Expand All @@ -28,7 +26,6 @@
import liquibase.util.StringUtils;
import liquibase.util.file.FilenameUtils;

import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
Expand Down
Expand Up @@ -46,7 +46,6 @@
import liquibase.servicelocator.ServiceLocator;
import liquibase.util.ISODateFormat;
import liquibase.util.LiquibaseUtil;
import liquibase.util.StreamUtil;
import liquibase.util.StringUtils;
import liquibase.util.xml.XMLResourceBundle;
import liquibase.util.xml.XmlResourceBundleControl;
Expand Down Expand Up @@ -287,7 +286,9 @@ public static int run(String[] args) throws LiquibaseException {
log.info(LogType.USER_MESSAGE, licenseService.getLicenseInfo());
}

if (main.commandParams.contains("--help") && main.command.startsWith("rollbackOneChangeSet")) {
if (main.commandParams.contains("--help") &&
(main.command.startsWith("rollbackOneChangeSet") ||
main.command.startsWith("rollbackOneUpdate"))) {
//don't need to check setup
} else {
List<String> setupMessages = main.checkSetup();
Expand Down Expand Up @@ -541,15 +542,17 @@ private static boolean isStandardOutputRequired(String command) {
private static boolean isChangeLogRequired(String command) {
return command.toLowerCase().startsWith(COMMANDS.UPDATE)
|| (command.toLowerCase().startsWith(COMMANDS.ROLLBACK) &&
!command.equalsIgnoreCase(COMMANDS.ROLLBACK_ONE_CHANGE_SET))
(!command.equalsIgnoreCase(COMMANDS.ROLLBACK_ONE_CHANGE_SET) &&
!command.equalsIgnoreCase(COMMANDS.ROLLBACK_ONE_UPDATE)))
|| COMMANDS.CALCULATE_CHECKSUM.equalsIgnoreCase(command)
|| COMMANDS.STATUS.equalsIgnoreCase(command)
|| COMMANDS.VALIDATE.equalsIgnoreCase(command)
|| COMMANDS.CHANGELOG_SYNC.equalsIgnoreCase(command)
|| COMMANDS.CHANGELOG_SYNC_SQL.equalsIgnoreCase(command)
|| COMMANDS.GENERATE_CHANGELOG.equalsIgnoreCase(command)
|| COMMANDS.DIFF_CHANGELOG.equalsIgnoreCase(command)
|| COMMANDS.ROLLBACK_ONE_CHANGE_SET.equalsIgnoreCase(command);
|| COMMANDS.ROLLBACK_ONE_CHANGE_SET.equalsIgnoreCase(command)
|| COMMANDS.ROLLBACK_ONE_UPDATE.equalsIgnoreCase(command);
}

/**
Expand Down Expand Up @@ -601,7 +604,9 @@ private static boolean isCommand(String arg) {
|| COMMANDS.MARK_NEXT_CHANGESET_RAN.equalsIgnoreCase(arg)
|| COMMANDS.MARK_NEXT_CHANGESET_RAN_SQL.equalsIgnoreCase(arg)
|| COMMANDS.ROLLBACK_ONE_CHANGE_SET.equalsIgnoreCase(arg)
|| COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equalsIgnoreCase(arg);
|| COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equalsIgnoreCase(arg)
|| COMMANDS.ROLLBACK_ONE_UPDATE.equalsIgnoreCase(arg)
|| COMMANDS.ROLLBACK_ONE_UPDATE_SQL.equalsIgnoreCase(arg);
}

/**
Expand Down Expand Up @@ -860,7 +865,6 @@ private void checkForUnexpectedCommandParameter(List<String> messages) {
} else if (COMMANDS.ROLLBACK_ONE_CHANGE_SET.equalsIgnoreCase(command)) {
for (String cmdParm : commandParams) {
if (!cmdParm.startsWith("--" + OPTIONS.CHANGE_SET_ID)
&& !cmdParm.startsWith("--" + OPTIONS.CHANGE_SET_ID)
&& !cmdParm.startsWith("--" + OPTIONS.HELP)
&& !cmdParm.startsWith("--" + OPTIONS.FORCE)
&& !cmdParm.startsWith("--" + OPTIONS.CHANGE_SET_PATH)
Expand All @@ -872,7 +876,6 @@ private void checkForUnexpectedCommandParameter(List<String> messages) {
} else if (COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equalsIgnoreCase(command)) {
for (String cmdParm : commandParams) {
if (!cmdParm.startsWith("--" + OPTIONS.CHANGE_SET_ID)
&& !cmdParm.startsWith("--" + OPTIONS.CHANGE_SET_ID)
&& !cmdParm.startsWith("--" + OPTIONS.HELP)
&& !cmdParm.startsWith("--" + OPTIONS.FORCE)
&& !cmdParm.startsWith("--" + OPTIONS.CHANGE_SET_PATH)
Expand All @@ -882,6 +885,24 @@ private void checkForUnexpectedCommandParameter(List<String> messages) {
}
}
}
else if (COMMANDS.ROLLBACK_ONE_UPDATE.equalsIgnoreCase(command)) {
for (String cmdParm : commandParams) {
if (!cmdParm.startsWith("--" + OPTIONS.DEPLOYMENT_ID)
&& !cmdParm.startsWith("--" + OPTIONS.HELP)
&& !cmdParm.startsWith("--" + OPTIONS.FORCE)) {
messages.add(String.format(coreBundle.getString("unexpected.command.parameter"), cmdParm));
}
}
}
else if (COMMANDS.ROLLBACK_ONE_UPDATE_SQL.equalsIgnoreCase(command)) {
for (String cmdParm : commandParams) {
if (!cmdParm.startsWith("--" + OPTIONS.DEPLOYMENT_ID)
&& !cmdParm.startsWith("--" + OPTIONS.HELP)
&& !cmdParm.startsWith("--" + OPTIONS.FORCE)) {
messages.add(String.format(coreBundle.getString("unexpected.command.parameter"), cmdParm));
}
}
}
}

/**
Expand Down Expand Up @@ -1278,9 +1299,12 @@ protected void doMigration() throws Exception {
//
// Check for a valid license to run PRO commands
//
if (COMMANDS.ROLLBACK_ONE_CHANGE_SET.equals(command) || COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equals(command)) {
if (COMMANDS.ROLLBACK_ONE_CHANGE_SET.equals(command) ||
COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equals(command) ||
COMMANDS.ROLLBACK_ONE_UPDATE.equals(command) ||
COMMANDS.ROLLBACK_ONE_UPDATE_SQL.equals(command)){
if (!commandParams.contains("--help") && !liquibaseProLicenseValid) {
String messageString = String.format(coreBundle.getString("no.pro.license.found"), COMMANDS.ROLLBACK_ONE_CHANGE_SET);
String messageString = String.format(coreBundle.getString("no.pro.license.found"), command);
throw new LiquibaseException(messageString);
}
}
Expand Down Expand Up @@ -1516,15 +1540,50 @@ protected void doMigration() throws Exception {
if (this.commandParams.contains("--help")) {
argsMap.put("help", true);
}
LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, argsMap);
LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_CHANGE_SET, argsMap);
liquibaseCommand.execute();
return;
} else if (COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equals(command)) {
Writer outputWriter = getOutputWriter();
Map<String, Object> argsMap = new HashMap<String, Object>();
argsMap.put("outputWriter", outputWriter);
argsMap.put("force", true);
LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, argsMap);
LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_CHANGE_SET, argsMap);
liquibaseCommand.execute();
outputWriter.flush();
outputWriter.close();
return;
} else if (COMMANDS.ROLLBACK_ONE_UPDATE.equals(command)) {
Map<String, Object> argsMap = new HashMap<String, Object>();
argsMap.put("deploymentId", getCommandParam(OPTIONS.DEPLOYMENT_ID, null));
argsMap.put("changeLogFile", changeLogFile);
argsMap.put("database", database);
if (!commandParams.contains("--help")) {
argsMap.put("changeLog", liquibase.getDatabaseChangeLog());
}
argsMap.put("resourceAccessor", liquibase.getResourceAccessor());
ChangeLogParameters clp = new ChangeLogParameters(database);
for (Map.Entry<String, Object> entry : changeLogParameters.entrySet()) {
clp.set(entry.getKey(), entry.getValue());
}
argsMap.put("changeLogParameters", clp);

if (this.commandParams.contains("--force")) {
argsMap.put("force", true);
}
if (this.commandParams.contains("--help")) {
argsMap.put("help", true);
}
LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_UPDATE, argsMap);
liquibaseCommand.execute();
return;
} else if (COMMANDS.ROLLBACK_ONE_UPDATE_SQL.equals(command)) {
Writer outputWriter = getOutputWriter();
Map<String, Object> argsMap = new HashMap<String, Object>();
argsMap.put("deploymentId", getCommandParam(OPTIONS.DEPLOYMENT_ID, null));
argsMap.put("outputWriter", outputWriter);
argsMap.put("force", true);
LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_UPDATE, argsMap);
liquibaseCommand.execute();
outputWriter.flush();
outputWriter.close();
Expand Down Expand Up @@ -1719,9 +1778,9 @@ protected void doMigration() throws Exception {
}
}

private LiquibaseCommand createLiquibaseCommand(Database database, Liquibase liquibase, Map<String, Object> argsMap)
private LiquibaseCommand createLiquibaseCommand(Database database, Liquibase liquibase, String commandName, Map<String, Object> argsMap)
throws CommandLineParsingException, LiquibaseException {
LiquibaseCommand liquibaseCommand = (CommandFactory.getInstance().getCommand(COMMANDS.ROLLBACK_ONE_CHANGE_SET));
LiquibaseCommand liquibaseCommand = CommandFactory.getInstance().getCommand(commandName);
AbstractSelfConfiguratingCommand configuratingCommand = (AbstractSelfConfiguratingCommand) liquibaseCommand;
argsMap.put("changeSetId", getCommandParam(OPTIONS.CHANGE_SET_ID, null));
argsMap.put("changeSetAuthor", getCommandParam(OPTIONS.CHANGE_SET_AUTHOR, null));
Expand Down Expand Up @@ -1904,6 +1963,8 @@ private enum COMMANDS {
private static final String RELEASE_LOCKS = "releaseLocks";
private static final String ROLLBACK_ONE_CHANGE_SET = "rollbackOneChangeSet";
private static final String ROLLBACK_ONE_CHANGE_SET_SQL = "rollbackOneChangeSetSQL";
private static final String ROLLBACK_ONE_UPDATE = "rollbackOneUpdate";
private static final String ROLLBACK_ONE_UPDATE_SQL = "rollbackOneUpdateSQL";
private static final String ROLLBACK = "rollback";
private static final String ROLLBACK_COUNT = "rollbackCount";
private static final String ROLLBACK_COUNT_SQL = "rollbackCountSQL";
Expand Down Expand Up @@ -1937,6 +1998,7 @@ private enum OPTIONS {
private static final String CHANGE_SET_ID = "changeSetId";
private static final String CHANGE_SET_AUTHOR = "changeSetAuthor";
private static final String CHANGE_SET_PATH = "changeSetPath";
private static final String DEPLOYMENT_ID = "deploymentId";
private static final String OUTPUT_FILE = "outputFile";
private static final String FORCE = "force";
private static final String ROLLBACK_SCRIPT = "rollbackScript";
Expand Down
Expand Up @@ -21,8 +21,8 @@ public static ValidationErrors checkForValidLicense(String licenseType, Change c
return new ValidationErrors();
}
if (licenseService.licenseIsValid(licenseType)) {
String message = String.format("Found valid license with subject '%s'",licenseType);
LOG.info(message);
String message = String.format("Found valid license with subject '%s' for '%s'",licenseType, change.getDescription());
LOG.debug(message);
return new ValidationErrors();
}

Expand Down
Expand Up @@ -33,6 +33,12 @@ Standard Commands:
rollbackOneChangeSetSQL <args> Writes SQL to roll back one specific changeset, without
rolling back changesets deployed before or afterwards.
(Liquibase Pro key required)
rollbackOneUpdate Rolls back all the changesets from one update, identified by "deploymentId",
if all the changesets can be rolled back. If not, a WARNING message will provide
details (Liquibase Pro key required). Note: A list of deploymentIds may be
viewed by using the "history" command.
rollbackOneUpdateSQL Displays the SQL which will be executed when the corresponding rollbackOneUpdate
command is executed, and does not perform the actual rollback (Liquibase Pro key required).
rollbackToDate <date/time> Rolls back the database to the the state is was
at the given date/time.
Date Format: yyyy-MM-dd'T'HH:mm:ss
Expand Down Expand Up @@ -74,9 +80,10 @@ Diff Commands
Documentation Commands
dbDoc <outputDirectory> Generates Javadoc-like documentation
based on current database and change log
history Writes details about what changeSets have been
applied to the database to standard out

history Displays the changesets already deployed to the
database in the specified connection url, grouped
by default according to their update command's
"deployment_id" value.
Maintenance Commands
tag <tag string> 'Tags' the current database state for future rollback
tagExists <tag string> Checks whether the given tag is already existing
Expand Down
Expand Up @@ -29,8 +29,11 @@ errors=Errors:
unexpected.value=Unexpected value '%s' (options must start with a '--')
cannot.specify.both=Cannot specify both '%s' and '%s'
changelogfile.already.exists=Output ChangeLogFile '%s' already exists!
force.option.required=The targeted changeset is followed by %d changesets, so unexpected outcomes may occur.\nTo review the rollback SQL, please run rollbackOneChangesetSQL. This message can be suppressed by\nadding the --force flag.
force.option.required=The targeted changeset is followed by %d changesets, so unexpected outcomes may occur.\nTo review the rollback SQL, please run '%s'. This message can be suppressed by\nadding the --force flag.
id.author.path.required=You must specify the change set ID, author, and path
no.deployment.ids.found=No deployment IDs were located. No rollbacks were performed.
no.change.sets.found.for.deployment.id=No changesets were located matching deployment ID '%s'. No rollbacks were performed.
deployment.id.required=You must specify the deployment ID.
no.pro.license.found=The command %s requires a Liquibase Pro license, available at https://download.liquibase.org/ or lbprosales@datical.com
attempt.to.delete.the.file.failed.cannot.continue=Attempt to delete the file '%s' failed. Cannot continue. Sorry.
successfully.released.database.change.log.locks=Successfully released all database change log locks for '%s'
Expand Down
Expand Up @@ -23,14 +23,14 @@
public abstract class AbstractLiquibaseChangeLogMojo extends AbstractLiquibaseMojo {

/**
* Specifies the directory where Liquibase can find your <i>change-log</i> file.
* Specifies the directory where Liquibase can find your <i>changelog</i> file.
*
* @parameter property="liquibase.changeLogDirectory"
*/
protected String changeLogDirectory;

/**
* Specifies the <i>change-log</i> file for Liquibase to use.
* Specifies the <i>changelog</i> file for Liquibase to use.
* @parameter property="liquibase.changeLogFile"
*/
protected String changeLogFile;
Expand Down