Skip to content

Commit

Permalink
point users to init project command if they forget a supported argume…
Browse files Browse the repository at this point in the history
…nt in any command (DAT-8641) (#2356)
  • Loading branch information
StevenMassaro committed Jan 19, 2022
1 parent 99f59c5 commit a9b2c81
Show file tree
Hide file tree
Showing 51 changed files with 233 additions and 161 deletions.
Expand Up @@ -2,6 +2,9 @@

import liquibase.command.CommandResults;
import liquibase.command.CommandScope;
import liquibase.command.CommonArgumentNames;
import liquibase.exception.CommandValidationException;
import liquibase.exception.MissingRequiredArgumentException;
import liquibase.util.StringUtil;
import picocli.CommandLine;

Expand All @@ -10,7 +13,10 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class CommandRunner implements Callable<CommandResults> {

Expand Down Expand Up @@ -43,6 +49,17 @@ public CommandResults call() throws Exception {
}

return commandScope.execute();
} catch (CommandValidationException cve) {
Throwable cause = cve.getCause();
if (cause instanceof MissingRequiredArgumentException) {
// This is a list of the arguments which the init project command supports. The thinking here is that if the user
// forgets to supply one of these arguments, we're going to remind them about the init project command, which
// can help them figure out what they should be providing here.
final Set<String> initProjectArguments = Stream.of(CommonArgumentNames.CHANGELOG_FILE, CommonArgumentNames.URL, CommonArgumentNames.USERNAME, CommonArgumentNames.PASSWORD).map(CommonArgumentNames::getArgumentName).collect(Collectors.toSet());
throw new CommandValidationException(cve.getMessage() + (initProjectArguments.contains(((MissingRequiredArgumentException) cause).getArgumentName()) ? ". If you need to configure new liquibase project files and arguments, run the 'liquibase init project' command." : ""));
} else {
throw cve;
}
} finally {
if (outputStream != null) {
outputStream.flush();
Expand Down
Expand Up @@ -4,6 +4,7 @@
import liquibase.configuration.ConfigurationValueConverter;
import liquibase.configuration.ConfigurationValueObfuscator;
import liquibase.exception.CommandValidationException;
import liquibase.exception.MissingRequiredArgumentException;
import liquibase.integration.commandline.LiquibaseCommandLineConfiguration;
import liquibase.util.ObjectUtil;

Expand Down Expand Up @@ -113,7 +114,7 @@ public ConfigurationValueObfuscator<DataType> getValueObfuscator() {
public void validate(CommandScope commandScope) throws CommandValidationException {
final DataType currentValue = commandScope.getArgumentValue(this);
if (this.isRequired() && currentValue == null) {
throw new CommandValidationException(LiquibaseCommandLineConfiguration.ARGUMENT_CONVERTER.getCurrentValue().convert(this.getName()), "missing required argument");
throw new CommandValidationException(LiquibaseCommandLineConfiguration.ARGUMENT_CONVERTER.getCurrentValue().convert(this.getName()), "missing required argument", new MissingRequiredArgumentException(this.getName()));
}
}

Expand Down
Expand Up @@ -21,6 +21,13 @@ public <DataType> CommandArgumentDefinition.Building<DataType> argument(String n
return new CommandArgumentDefinition.Building<>(commandNames, new CommandArgumentDefinition<>(name, type));
}

/**
* Starts the building of a new {@link CommandArgumentDefinition}.
*/
public <DataType> CommandArgumentDefinition.Building<DataType> argument(CommonArgumentNames argument, Class<DataType> type) {
return new CommandArgumentDefinition.Building<>(commandNames, new CommandArgumentDefinition<>(argument.getArgumentName(), type));
}

/**
* Starts the building of a new {@link CommandResultDefinition}.
*/
Expand Down
@@ -0,0 +1,21 @@
package liquibase.command;

/**
* A common place to store commonly used command argument names.
*/
public enum CommonArgumentNames {
USERNAME("username"),
PASSWORD("password"),
URL("url"),
CHANGELOG_FILE("changelogFile");

private final String argumentName;

CommonArgumentNames(String argumentName) {
this.argumentName = argumentName;
}

public String getArgumentName() {
return argumentName;
}
}
Expand Up @@ -20,9 +20,9 @@ public class CalculateChecksumCommandStep extends AbstractCliWrapperCommandStep

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("The root changelog file").build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -32,9 +32,9 @@ public class CalculateChecksumCommandStep extends AbstractCliWrapperCommandStep
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.description("The database password")
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.build();
Expand Down
Expand Up @@ -21,9 +21,9 @@ public class ChangelogSyncCommandStep extends AbstractCliWrapperCommandStep {

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("The root changelog file").build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -33,9 +33,9 @@ public class ChangelogSyncCommandStep extends AbstractCliWrapperCommandStep {
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.description("The database password")
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.build();
Expand Down
Expand Up @@ -21,9 +21,9 @@ public class ChangelogSyncSqlCommandStep extends AbstractCliWrapperCommandStep {

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("The root changelog file").build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -33,9 +33,9 @@ public class ChangelogSyncSqlCommandStep extends AbstractCliWrapperCommandStep {
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.description("The database password").build();
LABELS_ARG = builder.argument("labels", String.class)
Expand Down
Expand Up @@ -22,9 +22,9 @@ public class ChangelogSyncToTagCommandStep extends AbstractCliWrapperCommandStep

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("The root changelog file").build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -34,9 +34,9 @@ public class ChangelogSyncToTagCommandStep extends AbstractCliWrapperCommandStep
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.description("The database password").build();
LABELS_ARG = builder.argument("labels", String.class)
Expand Down
Expand Up @@ -22,9 +22,9 @@ public class ChangelogSyncToTagSqlCommandStep extends AbstractCliWrapperCommandS

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("The root changelog file").build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -34,9 +34,9 @@ public class ChangelogSyncToTagSqlCommandStep extends AbstractCliWrapperCommandS
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.description("The database password").build();
LABELS_ARG = builder.argument("labels", String.class)
Expand Down
Expand Up @@ -18,7 +18,7 @@ public class ClearChecksumsCommandStep extends AbstractCliWrapperCommandStep {

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -28,9 +28,9 @@ public class ClearChecksumsCommandStep extends AbstractCliWrapperCommandStep {
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.description("The database password").build();
}
Expand Down
Expand Up @@ -20,9 +20,9 @@ public class DbDocCommandStep extends AbstractCliWrapperCommandStep {

static {
CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class)
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class)
.description("The root changelog").required().build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -32,9 +32,9 @@ public class DbDocCommandStep extends AbstractCliWrapperCommandStep {
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.description("The database password")
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.build();
Expand Down
Expand Up @@ -25,7 +25,7 @@ public class DeactivateChangelogCommandStep extends AbstractCommandStep {

static {
final CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("The root changelog").build();
}

Expand Down
Expand Up @@ -42,7 +42,7 @@ public class DiffChangelogCommandStep extends AbstractCliWrapperCommandStep {
.description("The reference default schema name to use for the database connection").build();
REFERENCE_DEFAULT_CATALOG_NAME_ARG = builder.argument("referenceDefaultCatalogName", String.class)
.description("The reference default catalog name to use for the database connection").build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC target database connection URL").build();
DEFAULT_SCHEMA_NAME_ARG = builder.argument("defaultSchemaName", String.class)
.description("The default schema name to use for the database connection").build();
Expand All @@ -52,13 +52,13 @@ public class DiffChangelogCommandStep extends AbstractCliWrapperCommandStep {
.description("The JDBC driver class").build();
DRIVER_PROPERTIES_FILE_ARG = builder.argument("driverPropertiesFile", String.class)
.description("The JDBC driver properties file").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The target database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.description("The target database password")
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.build();
CHANGELOG_FILE_ARG = builder.argument("changelogFile", String.class).required()
CHANGELOG_FILE_ARG = builder.argument(CommonArgumentNames.CHANGELOG_FILE, String.class).required()
.description("Changelog file to write results").build();
EXCLUDE_OBJECTS_ARG = builder.argument("excludeObjects", String.class)
.description("Objects to exclude from diff").build();
Expand Down
Expand Up @@ -33,11 +33,11 @@ public class DiffCommandStep extends AbstractCliWrapperCommandStep {
.description("The reference database password")
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.build();
URL_ARG = builder.argument("url", String.class).required()
URL_ARG = builder.argument(CommonArgumentNames.URL, String.class).required()
.description("The JDBC target database connection URL").build();
USERNAME_ARG = builder.argument("username", String.class)
USERNAME_ARG = builder.argument(CommonArgumentNames.USERNAME, String.class)
.description("The target database username").build();
PASSWORD_ARG = builder.argument("password", String.class)
PASSWORD_ARG = builder.argument(CommonArgumentNames.PASSWORD, String.class)
.description("The target database password")
.setValueObfuscator(ConfigurationValueObfuscator.STANDARD)
.build();
Expand Down

0 comments on commit a9b2c81

Please sign in to comment.