From 4f0af6e80244be7e1fe51d03c9694e36af335846 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Fri, 3 Dec 2021 12:42:59 -0600 Subject: [PATCH 01/22] Fix issue with ConfiguredValue.wasDefaultValueUsed method Added more test setup code to create/delete resources DAT-8640 --- .../command/core/UpdateCommandStep.java | 2 +- .../configuration/ConfiguredValue.java | 10 +- .../main/java/liquibase/util/FileUtil.java | 2 +- .../testing/command/CommandTests.groovy | 92 ++++++++++++------- .../testing/setup/SetupCleanResources.groovy | 57 ++++++++---- .../SetupCreateDirectoryResources.groovy | 23 +++++ .../setup/SetupCreateTempResources.groovy | 8 +- .../testing/command/diffChangelog.test.groovy | 7 +- .../command/generateChangelog.test.groovy | 3 +- .../command/registerChangelog.test.groovy | 1 - 10 files changed, 137 insertions(+), 68 deletions(-) create mode 100644 liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateDirectoryResources.groovy diff --git a/liquibase-core/src/main/java/liquibase/command/core/UpdateCommandStep.java b/liquibase-core/src/main/java/liquibase/command/core/UpdateCommandStep.java index 431a6c6622a..9c74e496517 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/UpdateCommandStep.java +++ b/liquibase-core/src/main/java/liquibase/command/core/UpdateCommandStep.java @@ -26,7 +26,7 @@ public class UpdateCommandStep extends AbstractCliWrapperCommandStep { CommandBuilder builder = new CommandBuilder(COMMAND_NAME, LEGACY_COMMAND_NAME); URL_ARG = builder.argument("url", String.class).required() - .description("The JDBC database connection URL").build(); + .description("The JDBC database connection URL").build(); DEFAULT_SCHEMA_NAME = builder.argument("defaultSchemaName", String.class) .description("The default schema name to use for the database connection").build(); DEFAULT_CATALOG_NAME_ARG = builder.argument("defaultCatalogName", String.class) diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java b/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java index 23e8c57c444..483175ae691 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java @@ -56,15 +56,9 @@ public ProvidedValue getProvidedValue() { return getProvidedValues().get(0); } - public boolean wasDefaultValueUsed() { - for (ProvidedValue providedValue : this.getProvidedValues()) { - if (providedValue.getProvider() != null && providedValue.getProvider() instanceof ConfigurationDefinition.DefaultValueProvider) { - return true; - } - } - - return false; + ProvidedValue winningProvidedValue = getProvidedValue(); + return winningProvidedValue != null && winningProvidedValue.getProvider() instanceof ConfigurationDefinition.DefaultValueProvider; } /** diff --git a/liquibase-core/src/main/java/liquibase/util/FileUtil.java b/liquibase-core/src/main/java/liquibase/util/FileUtil.java index 699cb75bf31..92da8993f4b 100644 --- a/liquibase-core/src/main/java/liquibase/util/FileUtil.java +++ b/liquibase-core/src/main/java/liquibase/util/FileUtil.java @@ -11,7 +11,7 @@ private FileUtil() { throw new IllegalStateException("This utility class must not be instantiated. Sorry."); } - public static String getContents(File file) throws IOException { + public static String getContents(File file) throws IOException { if (!file.exists()) { return null; } diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index abcc9b8db99..b61aad4ffdc 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -21,6 +21,7 @@ import liquibase.database.jvm.JdbcConnection import liquibase.extension.testing.TestDatabaseConnections import liquibase.extension.testing.TestFilter import liquibase.extension.testing.setup.* +import liquibase.extension.testing.setup.SetupCleanResources.CleanupMode import liquibase.hub.HubService import liquibase.hub.core.MockHubService import liquibase.integration.commandline.LiquibaseCommandLineConfiguration @@ -290,13 +291,6 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} return } } - finally { - if (testDef.setup != null) { - for (def setup : testDef.setup) { - setup.cleanup() - } - } - } } as Scope.ScopedRunnerWithReturn) if (savedException != null && savedException.getCause() != null && savedException.getCause() instanceof CommandFailedException) { @@ -311,35 +305,43 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} throw new RuntimeException("Results were expected but none were found for " + testDef.commandTestDefinition.command) } - then: - checkOutput("Command Output", outputStream.toString(), testDef.expectedOutput) - checkOutput("UI Output", uiOutputWriter.toString(), testDef.expectedUI) - checkOutput("UI Error Output", uiErrorWriter.toString(), testDef.expectedUIErrors) - checkOutput("Log Messages", logService.getLogAsString(Level.FINE), testDef.expectedLogs) - - checkFileContent(testDef.expectedFileContent, "Command File Content") - checkDatabaseContent(testDef.expectedDatabaseContent, database, "Database snapshot content") - - if (!testDef.expectedResults.isEmpty()) { - for (def returnedResult : results.getResults().entrySet()) { - def expectedResult = testDef.expectedResults.get(returnedResult.getKey()) - def expectedValue = expectedResult instanceof Closure ? expectedResult.call() : String.valueOf(expectedResult) - def seenValue = String.valueOf(returnedResult.getValue()) - - assert expectedValue != "null": "No expectedResult for returned result '" + returnedResult.getKey() + "' of: " + seenValue - assert seenValue == expectedValue + try { + checkOutput("Command Output", outputStream.toString(), testDef.expectedOutput) + checkOutput("UI Output", uiOutputWriter.toString(), testDef.expectedUI) + checkOutput("UI Error Output", uiErrorWriter.toString(), testDef.expectedUIErrors) + checkOutput("Log Messages", logService.getLogAsString(Level.FINE), testDef.expectedLogs) + + checkFileContent(testDef.expectedFileContent, "Command File Content") + checkDatabaseContent(testDef.expectedDatabaseContent, database, "Database snapshot content") + + if (!testDef.expectedResults.isEmpty()) { + for (def returnedResult : results.getResults().entrySet()) { + def expectedResult = testDef.expectedResults.get(returnedResult.getKey()) + def expectedValue = expectedResult instanceof Closure ? expectedResult.call() : String.valueOf(expectedResult) + def seenValue = String.valueOf(returnedResult.getValue()) + + assert expectedValue != "null": "No expectedResult for returned result '" + returnedResult.getKey() + "' of: " + seenValue + assert seenValue == expectedValue + } + } + if (testDef.expectFileToExist != null) { + assert testDef.expectFileToExist.exists(): "File '${testDef.expectFileToExist.getAbsolutePath()}' should exist" + } + if (testDef.expectFileToNotExist != null) { + assert !testDef.expectFileToNotExist.exists(): "File '${testDef.expectFileToNotExist.getAbsolutePath()}' should not exist" + } + } finally { + if (testDef.setup != null) { + for (def setup : testDef.setup) { + setup.cleanup() + } + } } - } - if (testDef.expectFileToExist != null) { - assert testDef.expectFileToExist.exists(): "File '${testDef.expectFileToExist.getAbsolutePath()}' should exist" - } - if (testDef.expectFileToNotExist != null) { - assert !testDef.expectFileToNotExist.exists(): "File '${testDef.expectFileToNotExist.getAbsolutePath()}' should not exist" - } - where: - permutation << getAllRunTestPermutations() + + where: + permutation << getAllRunTestPermutations() } static OutputCheck assertNotContains(String substring) { @@ -836,10 +838,21 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} this.setups.add(new SetupRunChangelog(changeLogPath, labels)) } + /* + * Create files and directories + */ void createTempResource(String originalFile, String newFile) { this.setups.add(new SetupCreateTempResources(originalFile, newFile)) } + void createTempResource(String originalFile, String newFile, String baseDir) { + this.setups.add(new SetupCreateTempResources(originalFile, newFile, baseDir)) + } + + void createTempDirectoryResource(String directory) { + this.setups.add(new SetupCreateDirectoryResources(directory)) + } + /** * * Copy a specified file to another path @@ -865,13 +878,24 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} * * Delete the specified resources * - * @param fileToDeletes + * @param filesToDelete * */ void cleanResources(String... filesToDelete) { this.setups.add(new SetupCleanResources(filesToDelete)) } + /** + * + * Delete the specified resources at possibly setup and cleanup + * + * @param filesToDelete + * + */ + void cleanResources(CleanupMode cleanOnSetup, String... filesToDelete) { + this.setups.add(new SetupCleanResources(cleanOnSetup, filesToDelete)) + } + /** * Mark the changeSets within a changelog as ran without actually running them */ diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy index 66cb594cf82..40a8b8b60f2 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy @@ -1,41 +1,62 @@ package liquibase.extension.testing.setup -import liquibase.Contexts -import liquibase.LabelExpression -import liquibase.Liquibase -import liquibase.changelog.ChangeLogHistoryService -import liquibase.changelog.ChangeLogHistoryServiceFactory -import liquibase.database.Database -import liquibase.database.DatabaseFactory -import liquibase.database.jvm.JdbcConnection + import liquibase.extension.testing.TestDatabaseConnections -import liquibase.integration.commandline.CommandLineResourceAccessor -import liquibase.resource.CompositeResourceAccessor -import liquibase.resource.FileSystemResourceAccessor -import java.nio.file.Paths +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.Path class SetupCleanResources extends TestSetup { private final List resourcesToDelete = new ArrayList<>() + public enum CleanupMode { CLEAN_ON_SETUP, CLEAN_ON_CLEANUP, CLEAN_ON_BOTH} + private CleanupMode cleanupMode SetupCleanResources(String[] resourcesToDelete) { + this(CleanupMode.CLEAN_ON_CLEANUP, resourcesToDelete) + } + + SetupCleanResources(CleanupMode cleanupMode, String[] resourcesToDelete) { + this.cleanupMode = cleanupMode this.resourcesToDelete.addAll(resourcesToDelete as Set) } @Override void setup(TestDatabaseConnections.ConnectionStatus connectionStatus) throws Exception { + if (cleanupMode == CleanupMode.CLEAN_ON_CLEANUP) { + return + } + deleteFiles(resourcesToDelete) + } + + @Override + void cleanup() { + if (cleanupMode == CleanupMode.CLEAN_ON_SETUP) { + return + } + deleteFiles(resourcesToDelete) + } + + private void deleteFiles(List resourcesToDelete) { for (String fileToDelete : resourcesToDelete) { + File f = null URL url = Thread.currentThread().getContextClassLoader().getResource(fileToDelete) if (url == null) { - return + f = new File(fileToDelete) + } else { + f = new File(url.toURI()) } - File f = new File(url.toURI()) + + // + // This will handle files and directories + // if (f.exists()) { - boolean b = f.delete() - if (b) { - assert !f.exists(): "The file '$f' was not deleted" - } + Path path = FileSystems.getDefault().getPath(f.getAbsolutePath()); + Files.walk(path) + .sorted(Comparator.reverseOrder()) + .map({ p -> p.toFile() }) + .forEach({ file -> file.delete() }) } } } diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateDirectoryResources.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateDirectoryResources.groovy new file mode 100644 index 00000000000..4bdb2201240 --- /dev/null +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateDirectoryResources.groovy @@ -0,0 +1,23 @@ +package liquibase.extension.testing.setup + +import liquibase.extension.testing.TestDatabaseConnections + +class SetupCreateDirectoryResources extends TestSetup { + + private String directory + + SetupCreateDirectoryResources(String directory) { + this.directory = directory + } + + @Override + void setup(TestDatabaseConnections.ConnectionStatus connectionStatus) throws Exception { + File f = new File(directory) + boolean b = f.mkdirs() + if (! b) { + if (! f.exists()) { + throw new RuntimeException("Unable to create directory '" + directory + "'") + } + } + } +} diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy index cb015f02577..0de15a1aebd 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy @@ -7,10 +7,16 @@ class SetupCreateTempResources extends TestSetup { private String originalFile private String newFile + private String baseDir SetupCreateTempResources(String originalFile, String newFile) { + this(originalFile, newFile, "target/test-classes") + } + + SetupCreateTempResources(String originalFile, String newFile, String baseDir) { this.originalFile = originalFile this.newFile = newFile + this.baseDir = baseDir } @Override @@ -18,7 +24,7 @@ class SetupCreateTempResources extends TestSetup { URL url = Thread.currentThread().getContextClassLoader().getResource(originalFile) File f = new File(url.toURI()) String contents = FileUtil.getContents(f) - File outputFile = new File("target/test-classes", newFile) + File outputFile = new File(baseDir, newFile) FileUtil.write(contents, outputFile) } } diff --git a/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/diffChangelog.test.groovy b/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/diffChangelog.test.groovy index 1400e4eb921..d802cb4d082 100644 --- a/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/diffChangelog.test.groovy +++ b/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/diffChangelog.test.groovy @@ -7,6 +7,7 @@ import liquibase.change.core.AddPrimaryKeyChange import liquibase.change.core.CreateTableChange import liquibase.exception.CommandExecutionException import liquibase.exception.CommandValidationException +import liquibase.extension.testing.setup.SetupCleanResources import liquibase.structure.core.Column import java.util.regex.Pattern @@ -71,7 +72,7 @@ Optional Args: ] setup { - cleanResources("diffChangelog-test.xml") + cleanResources(SetupCleanResources.CleanupMode.CLEAN_ON_SETUP, "diffChangelog-test.xml") database = [ new CreateTableChange( tableName: "FirstTable", @@ -115,7 +116,7 @@ Optional Args: ] setup { - cleanResources("diffChangeLog-test.xml") + cleanResources(SetupCleanResources.CleanupMode.CLEAN_ON_SETUP, "diffChangeLog-test.xml") database = [ new CreateTableChange( tableName: "SharedTable", @@ -173,7 +174,7 @@ Optional Args: ] setup { - cleanResources("diffChangelogOrder-test.xml") + cleanResources(SetupCleanResources.CleanupMode.CLEAN_ON_SETUP, "diffChangelogOrder-test.xml") database = [ new CreateTableChange( tableName: "person", diff --git a/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/generateChangelog.test.groovy b/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/generateChangelog.test.groovy index eae820c7f38..79d5f189281 100644 --- a/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/generateChangelog.test.groovy +++ b/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/generateChangelog.test.groovy @@ -4,6 +4,7 @@ import liquibase.change.ColumnConfig import liquibase.change.core.CreateTableChange import liquibase.change.core.TagDatabaseChange import liquibase.exception.CommandValidationException +import liquibase.extension.testing.setup.SetupCleanResources CommandTests.define { command = ["generateChangelog"] @@ -51,7 +52,7 @@ Optional Args: changelogFile: "target/test-classes/changelog-test.xml" ] setup { - cleanResources("changelog-test.xml") + cleanResources(SetupCleanResources.CleanupMode.CLEAN_ON_SETUP, "changelog-test.xml") database = [ new CreateTableChange( tableName: "FirstTable", diff --git a/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/registerChangelog.test.groovy b/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/registerChangelog.test.groovy index eb83e9da85b..28bdd453618 100644 --- a/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/registerChangelog.test.groovy +++ b/liquibase-integration-tests/src/test/resources/liquibase/extension/testing/command/registerChangelog.test.groovy @@ -2,7 +2,6 @@ package liquibase.extension.testing.command import liquibase.exception.CommandExecutionException import liquibase.exception.CommandValidationException -import liquibase.extension.testing.setup.SetupCreateTempResources import liquibase.hub.core.MockHubService import java.util.regex.Pattern From acfc833049d21aae719e6e6f3ca121ab033e7a95 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Fri, 3 Dec 2021 17:16:58 -0600 Subject: [PATCH 02/22] Added a comment DAT-8724 --- .../java/liquibase/configuration/ConfiguredValue.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java b/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java index 483175ae691..1d0052238ff 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java @@ -45,7 +45,6 @@ public DataType getValueObfuscated() { return rawValue; } - /** * Returns the "winning" value across all the possible {@link ConfigurationValueProvider}. * A {@link ProvidedValue} is always returned, even if the value was not configured. @@ -56,6 +55,13 @@ public ProvidedValue getProvidedValue() { return getProvidedValues().get(0); } + /** + * + * Return true if a default value was the "winning" value + * + * @return boolean + * + */ public boolean wasDefaultValueUsed() { ProvidedValue winningProvidedValue = getProvidedValue(); return winningProvidedValue != null && winningProvidedValue.getProvider() instanceof ConfigurationDefinition.DefaultValueProvider; From 463e0b8b7c49cabd5fa9b290cf198497020945ff Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Tue, 7 Dec 2021 15:43:18 -0600 Subject: [PATCH 03/22] Potential fix for JDK 16 issue in CommandTests --- .../extension/testing/setup/SetupCleanResources.groovy | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy index 40a8b8b60f2..beddeb51ef7 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy @@ -48,9 +48,16 @@ class SetupCleanResources extends TestSetup { f = new File(url.toURI()) } + if (f.isFile()) { + f.delete() + } else { + f.deleteDir() + } + // // This will handle files and directories // + /* if (f.exists()) { Path path = FileSystems.getDefault().getPath(f.getAbsolutePath()); Files.walk(path) @@ -58,6 +65,7 @@ class SetupCleanResources extends TestSetup { .map({ p -> p.toFile() }) .forEach({ file -> file.delete() }) } + */ } } } From 2c70056777f6753a1d685f663da31dbb91eb1c11 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Thu, 9 Dec 2021 08:30:01 -0500 Subject: [PATCH 04/22] Move interactive prompting logic into core module (DAT-8642) (#2255) This PR (in combination with the Pro PR) does a few small things: Move the interactive CLI prompting logic into the core modules so they can be used outside of pro Add an interface for the enum which dictates the prompting logic. This is so that we can have separate promptable enums in the core and pro code and use the same abstract prompting logic for both. --- .../AbstractCommandLineValueGetter.java | 136 ++++++++++++++++++ .../ui/interactive/DynamicRuleParameter.java | 65 +++++++++ .../IInteractivelyPromptableEnum.java | 29 ++++ ...ractivePromptableCustomizationWrapper.java | 69 +++++++++ 4 files changed, 299 insertions(+) create mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java create mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java create mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java create mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java b/liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java new file mode 100644 index 00000000000..864add7e9b9 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java @@ -0,0 +1,136 @@ +package liquibase.ui.interactive; + +import liquibase.Scope; +import liquibase.ui.InputHandler; + +import java.util.List; + +/** + * This class represents the basis for prompts to the user to input values, and should be used as part of the process + * of obtaining user input for quality checks. + * @param the type the user is expected to enter + */ +public abstract class AbstractCommandLineValueGetter { + + /** + * The type of the value that will be obtained. + */ + private final Class clazz; + + /** + * Create a new value getter. + * @param clazz the type of the value that will be obtained + */ + public AbstractCommandLineValueGetter(Class clazz) { + this.clazz = clazz; + } + + /** + * Prompt the user to enter a value for a parameter, and include the existing value in the prompt. + * @param parameter the parameter to obtain a value for + * @param newParameterValues a list of the values that have already been entered by the user during this interactive CLI parameter prompting situation + * @return the value entered by the user + */ + public final T prompt(InteractivePromptableCustomizationWrapper parameter, List newParameterValues, Object currentValue) { + // determine which value should be displayed in square brackets as the value that will be selected if user presses enter + Object valueToPromptAsDefault; + if (currentValue != null) { + /* + * The value is being converted here, because enum types get read from the check settings file as strings. + * As a result, the default value and current value (which should be the same type), are not; the default + * value would be an enum and the current value would be a string. + */ + try { + valueToPromptAsDefault = convert((String) currentValue); + } catch (Exception e) { + valueToPromptAsDefault = currentValue; + } + } else { + valueToPromptAsDefault = parameter.getDefaultValue(); + } + + // assume the user just hit enter to accept the default and revalidate it, since hitting enter to accept the + // default skips the validation logic in ConsoleUIService. Reprompt endlessly until a valid value is entered. + T prompt = null; + boolean valid = false; + while (!valid && (prompt == null || prompt.equals(valueToPromptAsDefault))) { + prompt = doPrompt(parameter, newParameterValues, valueToPromptAsDefault, (currentValue != null || parameter.getDefaultValue() != null)); + + try { + valid = doValidate(parameter, newParameterValues, prompt); + } catch (IllegalArgumentException e) { + Scope.getCurrentScope().getUI().sendErrorMessage("Invalid value: '" + prompt + "': " + e.getMessage()); + } + } + return prompt; + } + + private T doPrompt(InteractivePromptableCustomizationWrapper parameter, List newParameterValues, Object valueToPromptAsDefault, boolean shouldAllowEmptyValues) { + return Scope.getCurrentScope().getUI().prompt(getMessage(parameter), (T) valueToPromptAsDefault, new InputHandler() { + @Override + public T parseInput(String input, Class type) throws IllegalArgumentException { + T convert; + try { + convert = AbstractCommandLineValueGetter.this.convert(input); + } catch (Exception e) { + if (e.getMessage() != null) { + throw new IllegalArgumentException( + String.format("Invalid value: '%s': %s", input, e.getMessage()), e); + } + throw new IllegalArgumentException(e); + } + + try { + if (!doValidate(parameter, newParameterValues, convert)) { + throw new IllegalArgumentException("The supplied value is not valid."); + } + } catch (Exception e) { + if (e.getMessage() != null) { + throw new IllegalArgumentException( + String.format("Invalid value: '%s': %s", input, e.getMessage()), e); + } + throw new IllegalArgumentException( + String.format("Invalid value: '%s': The supplied value is not valid.", input), e); + } + return convert; + } + + @Override + public boolean shouldAllowEmptyInput() { + // We do not allow empty input, because as of right now, all parameters require values. In the future, + // there may be parameters which permit empty values, which would need to tie in here. + return shouldAllowEmptyValues; + } + }, clazz); + } + + private boolean doValidate(InteractivePromptableCustomizationWrapper parameter, List newParameterValues, T convert) throws IllegalArgumentException { + if (parameter.getValidationCallbackOverride() != null) { + return parameter.getValidationCallbackOverride().apply(convert, newParameterValues); + } else { + return AbstractCommandLineValueGetter.this.validate(convert); + } + } + + /** + * Generate the prompt message. + * @param parameter the parameter to prompt for + * @return the message + */ + private String getMessage(InteractivePromptableCustomizationWrapper parameter) { + return parameter.getParameter().getUiMessage() + " (options: " + parameter.getParameter().getOptions() + ")"; + } + + /** + * Given the input from the user, after being converted, validate it. + * @return true if it is valid + */ + public abstract boolean validate(T input); + + /** + * Given the raw input string from the user, convert it to the right type. + * @param input the raw input string from the prompt + * @return the converted input + */ + public abstract T convert(String input); +} diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java b/liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java new file mode 100644 index 00000000000..16023baf104 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java @@ -0,0 +1,65 @@ +package liquibase.ui.interactive; + + +import java.util.Objects; + + +public class DynamicRuleParameter { + + /** + * The actual underlying DynamicRuleParameterEnum that corresponds to this value. We store the parameter as a string, + * because different versions of Liquibase might not contain the enum that the rule requires. We want to be able to + * parse newer conf files with older versions of Liquibase, without a SnakeYaml error that it cannot find the enum + * value. + */ + private String parameter; + private Object value; + + /** + * Constructor for SnakeYaml + */ + public DynamicRuleParameter() { + } + + public DynamicRuleParameter(IInteractivelyPromptableEnum parameter, Object value) { + Objects.requireNonNull(parameter); + this.parameter = parameter.toString(); + this.value = value; + } + + public DynamicRuleParameter(String parameter, Object value) { + Objects.requireNonNull(parameter); + this.parameter = parameter; + this.value = value; + } + + public String getParameter() { + return parameter; + } + + public void setParameter(String parameter) { + this.parameter = parameter; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DynamicRuleParameter that = (DynamicRuleParameter) o; + return Objects.equals(parameter, that.parameter) && value.equals(that.value); + } + + @Override + public int hashCode() { + return Objects.hash(parameter, value); + } +} + diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java b/liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java new file mode 100644 index 00000000000..ed76c26679b --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java @@ -0,0 +1,29 @@ +package liquibase.ui.interactive; + + +public interface IInteractivelyPromptableEnum { + /** + * Description of the parameter to be used in the UI output. + */ + String getDescription(); + + /** + * The default value of the parameter if the parameter has not been customized. + */ + Object getDefaultValue(); + + /** + * The implementation of the value getter that will be used to prompt the user to input a value. + */ + AbstractCommandLineValueGetter getInteractiveCommandLineValueGetter(); + + /** + * Parameter message to be used in the UI output. + */ + String getUiMessage(); + + /* + * Possible options for this parameter + */ + String getOptions(); +} diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java b/liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java new file mode 100644 index 00000000000..be0659ae562 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java @@ -0,0 +1,69 @@ +package liquibase.ui.interactive; + + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * This class exists to wrap the parameter enum so that individual usages can provide specific + * overrides of the logic defined in the enum class. You should access the underlying parameter as little as possible + * and instead, access it using getter wrapper methods in this class. That will allow future developers to specify + * custom overrides for each rule (for example, overriding the default value for a specific usage without + * affecting all others). + */ +public class InteractivePromptableCustomizationWrapper { + private final IInteractivelyPromptableEnum parameter; + private final BiFunction, Boolean> validationCallbackOverride; + private final Function, Boolean> shouldPrompt; + + public InteractivePromptableCustomizationWrapper(IInteractivelyPromptableEnum parameter) { + this.parameter = parameter; + this.validationCallbackOverride = null; + this.shouldPrompt = null; + } + + public InteractivePromptableCustomizationWrapper(IInteractivelyPromptableEnum parameter, BiFunction, Boolean> validationCallbackOverride, Function, Boolean> shouldPrompt) { + this.parameter = parameter; + this.validationCallbackOverride = validationCallbackOverride; + this.shouldPrompt = shouldPrompt; + } + + public Object getDefaultValue() { + return parameter.getDefaultValue(); + } + + public IInteractivelyPromptableEnum getParameter() { + return parameter; + } + + public AbstractCommandLineValueGetter getInteractiveCommandLineValueGetter() { + return parameter.getInteractiveCommandLineValueGetter(); + } + + public BiFunction, Boolean> getValidationCallbackOverride() { + return validationCallbackOverride; + } + + public Function, Boolean> getShouldPrompt() { + return shouldPrompt; + } + + @Override + public String toString() { + return getParameter().toString(); + } + + /** + * Determine if the rule parameter should be prompted for in a checks customize scenario. + * @param existingNewValues the values already provided in the checks customize session + * @return true if the prompt should occur for this parameter, false if not + */ + public boolean shouldPrompt(List existingNewValues) { + boolean resp = true; + if (shouldPrompt != null) { + resp = shouldPrompt.apply(existingNewValues); + } + return resp; + } +} From f9dd0ad53e4ba7e978767e50cb58aa58c5fc0027 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Thu, 9 Dec 2021 14:23:35 -0600 Subject: [PATCH 05/22] LB-2177 New content --- .../examples/json/example-changelog.json | 120 ++++++++++++++++++ .../examples/json/example-changeset.json | 30 +++++ .../examples/json/liquibase.properties | 76 +++++++++++ .../liquibase/examples/sql/blankchangelog.sql | 12 ++ .../examples/sql/example-changelog.sql | 23 ++++ .../examples/sql/example-changeset.sql | 7 + .../examples/sql/liquibase.properties | 76 +++++++++++ .../examples/sql/liquibase.sqlplus.conf | 47 +++++++ .../resources/liquibase/examples/start-h2 | 41 ++++++ .../resources/liquibase/examples/start-h2.bat | 34 +++++ .../examples/xml/blank.changelog.xml | 18 +++ .../examples/xml/example-changelog.xml | 43 +++++++ .../examples/xml/example-changeset.xml | 13 ++ .../examples/xml/liquibase.properties | 76 +++++++++++ .../examples/xml/liquibase.sqlplus.conf | 47 +++++++ .../examples/yaml/example-changelog.yaml | 48 +++++++ .../examples/yaml/example-changeset.yaml | 17 +++ .../examples/yaml/liquibase.properties | 76 +++++++++++ .../src/main/assembly/assembly-bin.xml | 7 + .../src/main/install4j/liquibase.install4j | 2 +- 20 files changed, 812 insertions(+), 1 deletion(-) create mode 100644 liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json create mode 100644 liquibase-core/src/main/resources/liquibase/examples/json/example-changeset.json create mode 100644 liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties create mode 100644 liquibase-core/src/main/resources/liquibase/examples/sql/blankchangelog.sql create mode 100644 liquibase-core/src/main/resources/liquibase/examples/sql/example-changelog.sql create mode 100644 liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset.sql create mode 100644 liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties create mode 100644 liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf create mode 100644 liquibase-core/src/main/resources/liquibase/examples/start-h2 create mode 100644 liquibase-core/src/main/resources/liquibase/examples/start-h2.bat create mode 100644 liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml create mode 100644 liquibase-core/src/main/resources/liquibase/examples/xml/example-changelog.xml create mode 100644 liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset.xml create mode 100644 liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties create mode 100644 liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf create mode 100644 liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml create mode 100644 liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset.yaml create mode 100644 liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json b/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json new file mode 100644 index 00000000000..3cef3ef10b4 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json @@ -0,0 +1,120 @@ +{ "databaseChangeLog": [ + "changeset": { + "id": "1", + "author": "your.name", + "changes": [ + { + "createTable": + { + "tablename": "person", + "columns": [ + { + "column": { + "name": "id", + "type": "int", + "autoincrement": true, + "constraints": { + "primarykey": true, + "nullable": false + } + } + }, + { + "column": { + "name": "name", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss1", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss2", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "city", + "type": "varchar(30)" + } + } + ] + } + } + ] + }, + "changeset": { + "id": "2", + "author": "your.name", + "changes": [ + { + "createTable": + { + "tablename": "company", + "columns": [ + { + "column": { + "name": "id", + "type": "int", + "autoincrement": true, + "constraints": { + "primarykey": true, + "nullable": false + } + } + }, + { + "column": { + "name": "name", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss1", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss2", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "city", + "type": "varchar(30)" + } + } + ] + } + } + ] + }, + "changeset": { + "id": "3", + "author": "your.name", + "changes": [ + { + "addColumn": + { + "tablename": "company", + "columns": [ + { + "column": { + "name": "country", + "type": "varchar(2)" + } + } + ] + } + } + ] + } +]} diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/example-changeset.json b/liquibase-core/src/main/resources/liquibase/examples/json/example-changeset.json new file mode 100644 index 00000000000..4c7e5d572a7 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/json/example-changeset.json @@ -0,0 +1,30 @@ +"changeSet": { + "id": "1", + "author": "dev", + "changes": [ + { + "createTable": { + "tableName": "person", + "columns": [ + { + "column": { + "name": "id", + "type": "int", + "autoIncrement": true, + "constraints": { + "primaryKey": true, + "nullable": false + } + } + }, + { + "column": { + "name": "name", + "type": "varchar(255)" + } + } + ] + } + } + ] +} diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties new file mode 100644 index 00000000000..5c2fd4e9888 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/json/liquibase.properties @@ -0,0 +1,76 @@ +#### _ _ _ _ +## | | (_) (_) | +## | | _ __ _ _ _ _| |__ __ _ ___ ___ +## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ +## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ +## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| +## | | +## |_| +## +## The liquibase.properties file stores properties which do not change often, +## such as database connection information. Properties stored here save time +## and reduce risk of mistyped command line arguments. +## Learn more: https://www.liquibase.org/documentation/config_properties.html +#### +#### +## Note about relative and absolute paths: +## The liquibase.properties file requires paths for some properties. +## The classpath is the path/to/resources (ex. src/main/resources). +## The changeLogFile path is relative to the classpath. +## The url H2 example below is relative to 'pwd' resource. +#### +# Enter the path for your changelog file. +changeLogFile=example-changelog.json + +#### Enter the Target database 'url' information #### +liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev + +# Enter the username for your Target database. +liquibase.command.username: dbuser + +# Enter the password for your Target database. +liquibase.command.password: letmein + +#### Enter the Source Database 'referenceUrl' information #### +## The source database is the baseline or reference against which your target database is compared for diff/diffchangelog commands. + +# Enter URL for the source database +liquibase.command.referenceUrl: jdbc:h2:tcp://localhost:9090/mem:integration + +# Enter the username for your source database +liquibase.command.referenceUsername: dbuser + +# Enter the password for your source database +liquibase.command.referencePassword: letmein + +# Logging Configuration +# logLevel controls the amount of logging information generated. If not set, the default logLevel is INFO. +# Valid values, from least amount of logging to most, are: +# OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL +# If you are having problems, setting the logLevel to DEBUG and re-running the command can be helpful. +# logLevel: DEBUG + +# The logFile property controls where logging messages are sent. If this is not set, then logging messages are +# displayed on the console. If this is set, then messages will be sent to a file with the given name. +# logFile: liquibase.log + + +#### Liquibase Pro Key Information #### +# Learn more, contact support, or get or renew a Pro Key at https://www.liquibase.com/protrial +# liquibase.pro.licensekey: + +#### Liquibase Hub Information #### +# Liquibase Hub is a free secure SaaS portal providing status reporting, monitoring & insights +# into your Liquibase database release automation. +# https://hub.liquibase.com + +## Add your free Hub API key here +# liquibase.hub.apikey: +# liquibase.hub.mode:all + + + + +## Get documentation at docs.liquibase.com ## +## Get certified courses at learn.liquibase.com ## +## Get support at liquibase.com/support ## diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/blankchangelog.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/blankchangelog.sql new file mode 100644 index 00000000000..b82062b1789 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/blankchangelog.sql @@ -0,0 +1,12 @@ +--liquibase formatted sql +/* https://www.liquibase.org/documentation/sql_format.html */ + +--changeset authorname:1 +/* Insert SQL change objects here */ + + +--changeset authorname:2 +/* Insert SQL change objects here */ + + + diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/example-changelog.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changelog.sql new file mode 100644 index 00000000000..5e89d1b7aef --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changelog.sql @@ -0,0 +1,23 @@ +--liquibase formatted sql + +--changeset your.name:1 +create table person ( + id int primary key, + name varchar(50) not null, + address1 varchar(50), + address2 varchar(50), + city varchar(30) +) + +--changeset your.name:2 +create table company ( + id int primary key, + name varchar(50) not null, + address1 varchar(50), + address2 varchar(50), + city varchar(30) +) + +--changeset other.dev:3 +alter table person add column country varchar(2) + diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset.sql new file mode 100644 index 00000000000..72fd788ec8e --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset.sql @@ -0,0 +1,7 @@ +(example-changeset.sql) + +--changeset dev:1 +create table test1( + id int primary key, + name varchar(255) +); diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties new file mode 100644 index 00000000000..1f30dc71cea --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties @@ -0,0 +1,76 @@ +#### _ _ _ _ +## | | (_) (_) | +## | | _ __ _ _ _ _| |__ __ _ ___ ___ +## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ +## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ +## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| +## | | +## |_| +## +## The liquibase.properties file stores properties which do not change often, +## such as database connection information. Properties stored here save time +## and reduce risk of mistyped command line arguments. +## Learn more: https://www.liquibase.org/documentation/config_properties.html +#### +#### +## Note about relative and absolute paths: +## The liquibase.properties file requires paths for some properties. +## The classpath is the path/to/resources (ex. src/main/resources). +## The changeLogFile path is relative to the classpath. +## The url H2 example below is relative to 'pwd' resource. +#### +# Enter the path for your changelog file. +changeLogFile=samplechangelog.h2.sql + +#### Enter the Target database 'url' information #### +liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev + +# Enter the username for your Target database. +liquibase.command.username: dbuser + +# Enter the password for your Target database. +liquibase.command.password: letmein + +#### Enter the Source Database 'referenceUrl' information #### +## The source database is the baseline or reference against which your target database is compared for diff/diffchangelog commands. + +# Enter URL for the source database +liquibase.command.referenceUrl: jdbc:h2:tcp://localhost:9090/mem:integration + +# Enter the username for your source database +liquibase.command.referenceUsername: dbuser + +# Enter the password for your source database +liquibase.command.referencePassword: letmein + +# Logging Configuration +# logLevel controls the amount of logging information generated. If not set, the default logLevel is INFO. +# Valid values, from least amount of logging to most, are: +# OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL +# If you are having problems, setting the logLevel to DEBUG and re-running the command can be helpful. +# logLevel: DEBUG + +# The logFile property controls where logging messages are sent. If this is not set, then logging messages are +# displayed on the console. If this is set, then messages will be sent to a file with the given name. +# logFile: liquibase.log + + +#### Liquibase Pro Key Information #### +# Learn more, contact support, or get or renew a Pro Key at https://www.liquibase.com/protrial +# liquibase.pro.licensekey: + +#### Liquibase Hub Information #### +# Liquibase Hub is a free secure SaaS portal providing status reporting, monitoring & insights +# into your Liquibase database release automation. +# https://hub.liquibase.com + +## Add your free Hub API key here +# liquibase.hub.apikey: +# liquibase.hub.mode:all + + + + +## Get documentation at docs.liquibase.com ## +## Get certified courses at learn.liquibase.com ## +## Get support at liquibase.com/support ## diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf new file mode 100644 index 00000000000..f6afd2cbcb6 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.sqlplus.conf @@ -0,0 +1,47 @@ +#### _ _ _ _ _____ +## | | (_) (_) | | __ \ +## | | _ __ _ _ _ _| |__ __ _ ___ ___ | |__) | __ ___ +## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ | ___/ '__/ _ \ +## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ | | | | | (_) | +## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| |_| |_| \___/ +## | | +## |_| +## +## The liquibase.sqlplus.conf file stores properties which are used during the +## execution of the Oracle SQLPLUS tool. +## Learn more: https://www.liquibase.org/documentation/config_properties.html +#### +#### +## Note about relative and absolute paths: +## The liquibase.sqlplus.path must be a valid path to the SQLPlUS executable. +## The liquibase.sqlplus.timeout value can be one of: +## -1 - disable the timeout +## Any integer value > 0 (measured in seconds) +## +#### + +# The full path to the SQLPLUS executable. +# Sample linux path +# liquibase.sqlplus.path=/apps/app/12.2.0.1.0/oracle/product/12.2.0.1.0/client_1/bin/sqlplus +# Sample windows path +# liquibase.sqlplus.path=c:\\oracle\\product\\11.2.0\\client_1\\bin\\sqlplus.exe + +# A valid timeout value for the execution of the SQLPLUS tool +liquibase.sqlplus.timeout=-1 + +# Flag to indicate whether or not to keep the temporary SQL file after execution of SQLPLUS. +# True = keep False = delete (default) +liquibase.sqlplus.keep.temp=true + +# OPTIONAL Flag to designate the location to store temporary SQL file after execution of SQLPLUS. +# Liquibase will attempt to use path exactly as entered, so please ensure it complies with your OS requirements. +# liquibase.sqlplus.keep.temp.path= + +# OPTIONAL Flag to designate the name of temporary SQL file after execution of SQLPLUS. +# Liquibase will attempt to use the name exactly as entered, so please ensure it complies with your OS requirements. +# liquibase.sqlplus.keep.temp.name= + +# OPTIONAL Args to pass directly to SQLPLUS. +# Learn about SQLPLUS args at https://docs.oracle.com/cd/B10501_01/server.920/a90842/ch4.htm +# Note: The delimiter for args is a space eg:" " and not "," or ";" separated. +# liquibase.sqlplus.args= diff --git a/liquibase-core/src/main/resources/liquibase/examples/start-h2 b/liquibase-core/src/main/resources/liquibase/examples/start-h2 new file mode 100644 index 00000000000..718090807bf --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/start-h2 @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +if [ -z "${LIQUIBASE_HOME}" ]; then + #liquibase home is not set + + LIQUIBASE_PATH="$(which liquibase)" + + if [ -z "${LIQUIBASE_PATH}" ]; then + echo "Must set LIQUIBASE_HOME environment variable, or have liquibase in your PATH" + exit 1 + fi + + LIQUIBASE_HOME=$(dirname "$(which liquibase)") +fi + +if [ -z "${JAVA_HOME}" ]; then + #JAVA_HOME not set, try to find a bundled version + if [ -d "${LIQUIBASE_HOME}/jre" ]; then + JAVA_HOME="$LIQUIBASE_HOME/jre" + elif [ -d "${LIQUIBASE_HOME}/.install4j/jre.bundle/Contents/Home" ]; then + JAVA_HOME="${LIQUIBASE_HOME}/.install4j/jre.bundle/Contents/Home" + fi +fi + +if [ -z "${JAVA_HOME}" ]; then + JAVA_PATH="$(which java)" + + if [ -z "${JAVA_PATH}" ]; then + echo "Cannot find java in your path. Install java or use the JAVA_HOME environment variable" + + exit 1 + fi +else + #Use path in JAVA_HOME + JAVA_PATH="${JAVA_HOME}/bin/java" +fi + + +# echo "${JAVA_PATH}" -cp "${LIQUIBASE_HOME}/lib/h2-1.4.200.jar:${LIQUIBASE_HOME}/liquibase.jar" liquibase.example.StartH2Main + +"${JAVA_PATH}" -cp "${LIQUIBASE_HOME}/lib/h2-1.4.200.jar:${LIQUIBASE_HOME}/liquibase.jar" liquibase.example.StartH2Main diff --git a/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat b/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat new file mode 100644 index 00000000000..21603ba57e4 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/start-h2.bat @@ -0,0 +1,34 @@ +@echo off +if "%OS%" == "Windows_NT" setlocal + +setlocal enabledelayedexpansion + +rem %~dp0 is expanded pathname of the current script under NT +rem %~p0 is the directory of the current script + +if exist %~p0\..\liquibase.jar SET LIQUIBASE_HOME="%~p0\.." + +if "%LIQUIBASE_HOME%"=="" ( + FOR /F "tokens=* USEBACKQ" %%g IN (`where liquibase.bat`) do (SET "LIQUIBASE_HOME=%%~dpg") +) + +if "%LIQUIBASE_HOME%"=="" ( + echo "Must set LIQUIBASE_HOME environment variable, or have liquibase.bat in your PATH" + exit /B 1 +) + +if "%JAVA_HOME%"=="" ( + + rem check for jre dir in liquibase_home + if NOT "%LIQUIBASE_HOME%"=="" if exist "%LIQUIBASE_HOME%\jre" ( + set JAVA_HOME=%LIQUIBASE_HOME%\jre + ) +) + +if "%JAVA_HOME%"=="" ( + set JAVA_PATH=java +) else ( + set JAVA_PATH=%JAVA_HOME%\bin\java +) + +"%JAVA_PATH%" -cp "%LIQUIBASE_HOME%\lib\h2-1.4.200.jar;%LIQUIBASE_HOME%\liquibase.jar" liquibase.example.StartH2Main diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml b/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml new file mode 100644 index 00000000000..fc9b1d763d1 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/example-changelog.xml b/liquibase-core/src/main/resources/liquibase/examples/xml/example-changelog.xml new file mode 100644 index 00000000000..cee6908804b --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/example-changelog.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset.xml b/liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset.xml new file mode 100644 index 00000000000..4f162b30621 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties new file mode 100644 index 00000000000..30b30d9ee9b --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.properties @@ -0,0 +1,76 @@ +#### _ _ _ _ +## | | (_) (_) | +## | | _ __ _ _ _ _| |__ __ _ ___ ___ +## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ +## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ +## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| +## | | +## |_| +## +## The liquibase.properties file stores properties which do not change often, +## such as database connection information. Properties stored here save time +## and reduce risk of mistyped command line arguments. +## Learn more: https://www.liquibase.org/documentation/config_properties.html +#### +#### +## Note about relative and absolute paths: +## The liquibase.properties file requires paths for some properties. +## The classpath is the path/to/resources (ex. src/main/resources). +## The changeLogFile path is relative to the classpath. +## The url H2 example below is relative to 'pwd' resource. +#### +# Enter the path for your changelog file. +changeLogFile=example-changelog.xml + +#### Enter the Target database 'url' information #### +liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev + +# Enter the username for your Target database. +liquibase.command.username: dbuser + +# Enter the password for your Target database. +liquibase.command.password: letmein + +#### Enter the Source Database 'referenceUrl' information #### +## The source database is the baseline or reference against which your target database is compared for diff/diffchangelog commands. + +# Enter URL for the source database +liquibase.command.referenceUrl: jdbc:h2:tcp://localhost:9090/mem:integration + +# Enter the username for your source database +liquibase.command.referenceUsername: dbuser + +# Enter the password for your source database +liquibase.command.referencePassword: letmein + +# Logging Configuration +# logLevel controls the amount of logging information generated. If not set, the default logLevel is INFO. +# Valid values, from least amount of logging to most, are: +# OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL +# If you are having problems, setting the logLevel to DEBUG and re-running the command can be helpful. +# logLevel: DEBUG + +# The logFile property controls where logging messages are sent. If this is not set, then logging messages are +# displayed on the console. If this is set, then messages will be sent to a file with the given name. +# logFile: liquibase.log + + +#### Liquibase Pro Key Information #### +# Learn more, contact support, or get or renew a Pro Key at https://www.liquibase.com/protrial +# liquibase.pro.licensekey: + +#### Liquibase Hub Information #### +# Liquibase Hub is a free secure SaaS portal providing status reporting, monitoring & insights +# into your Liquibase database release automation. +# https://hub.liquibase.com + +## Add your free Hub API key here +# liquibase.hub.apikey: +# liquibase.hub.mode:all + + + + +## Get documentation at docs.liquibase.com ## +## Get certified courses at learn.liquibase.com ## +## Get support at liquibase.com/support ## diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf new file mode 100644 index 00000000000..f6afd2cbcb6 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/liquibase.sqlplus.conf @@ -0,0 +1,47 @@ +#### _ _ _ _ _____ +## | | (_) (_) | | __ \ +## | | _ __ _ _ _ _| |__ __ _ ___ ___ | |__) | __ ___ +## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ | ___/ '__/ _ \ +## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ | | | | | (_) | +## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| |_| |_| \___/ +## | | +## |_| +## +## The liquibase.sqlplus.conf file stores properties which are used during the +## execution of the Oracle SQLPLUS tool. +## Learn more: https://www.liquibase.org/documentation/config_properties.html +#### +#### +## Note about relative and absolute paths: +## The liquibase.sqlplus.path must be a valid path to the SQLPlUS executable. +## The liquibase.sqlplus.timeout value can be one of: +## -1 - disable the timeout +## Any integer value > 0 (measured in seconds) +## +#### + +# The full path to the SQLPLUS executable. +# Sample linux path +# liquibase.sqlplus.path=/apps/app/12.2.0.1.0/oracle/product/12.2.0.1.0/client_1/bin/sqlplus +# Sample windows path +# liquibase.sqlplus.path=c:\\oracle\\product\\11.2.0\\client_1\\bin\\sqlplus.exe + +# A valid timeout value for the execution of the SQLPLUS tool +liquibase.sqlplus.timeout=-1 + +# Flag to indicate whether or not to keep the temporary SQL file after execution of SQLPLUS. +# True = keep False = delete (default) +liquibase.sqlplus.keep.temp=true + +# OPTIONAL Flag to designate the location to store temporary SQL file after execution of SQLPLUS. +# Liquibase will attempt to use path exactly as entered, so please ensure it complies with your OS requirements. +# liquibase.sqlplus.keep.temp.path= + +# OPTIONAL Flag to designate the name of temporary SQL file after execution of SQLPLUS. +# Liquibase will attempt to use the name exactly as entered, so please ensure it complies with your OS requirements. +# liquibase.sqlplus.keep.temp.name= + +# OPTIONAL Args to pass directly to SQLPLUS. +# Learn about SQLPLUS args at https://docs.oracle.com/cd/B10501_01/server.920/a90842/ch4.htm +# Note: The delimiter for args is a space eg:" " and not "," or ";" separated. +# liquibase.sqlplus.args= diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml new file mode 100644 index 00000000000..0ca1741a930 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml @@ -0,0 +1,48 @@ +databaseChangeLog: +- changeLogId: 455d447e-d2c9-42f1-b283-0cc524934a51 +- changeSet: + id: 1 + author: your.name + changes: + - createTable: + tableName: person + columns: + - column: + name: id + type: int + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: name + type: varchar(50) + +- changeSet: + id: 2 + author: your.name + changes: + - createTable: + tableName: company + columns: + - column: + name: id + type: int + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: name + type: varchar(50) + +- changeSet: + id: 3 + author: your.name + changes: + - addColumn: + tableName: company + columns: + - column: + name: id + type: varchar(2) diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset.yaml new file mode 100644 index 00000000000..ac332f2bf23 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset.yaml @@ -0,0 +1,17 @@ + - changeSet: + id: 1 + author: dev + changes: + - createTable: + tableName: person + columns: + - column: + name: id + type: int + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: name + type: varchar(255) diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties new file mode 100644 index 00000000000..f964af53f06 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/liquibase.properties @@ -0,0 +1,76 @@ +#### _ _ _ _ +## | | (_) (_) | +## | | _ __ _ _ _ _| |__ __ _ ___ ___ +## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ +## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ +## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| +## | | +## |_| +## +## The liquibase.properties file stores properties which do not change often, +## such as database connection information. Properties stored here save time +## and reduce risk of mistyped command line arguments. +## Learn more: https://www.liquibase.org/documentation/config_properties.html +#### +#### +## Note about relative and absolute paths: +## The liquibase.properties file requires paths for some properties. +## The classpath is the path/to/resources (ex. src/main/resources). +## The changeLogFile path is relative to the classpath. +## The url H2 example below is relative to 'pwd' resource. +#### +# Enter the path for your changelog file. +changeLogFile=example-changelog.yaml + +#### Enter the Target database 'url' information #### +liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev + +# Enter the username for your Target database. +liquibase.command.username: dbuser + +# Enter the password for your Target database. +liquibase.command.password: letmein + +#### Enter the Source Database 'referenceUrl' information #### +## The source database is the baseline or reference against which your target database is compared for diff/diffchangelog commands. + +# Enter URL for the source database +liquibase.command.referenceUrl: jdbc:h2:tcp://localhost:9090/mem:integration + +# Enter the username for your source database +liquibase.command.referenceUsername: dbuser + +# Enter the password for your source database +liquibase.command.referencePassword: letmein + +# Logging Configuration +# logLevel controls the amount of logging information generated. If not set, the default logLevel is INFO. +# Valid values, from least amount of logging to most, are: +# OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL +# If you are having problems, setting the logLevel to DEBUG and re-running the command can be helpful. +# logLevel: DEBUG + +# The logFile property controls where logging messages are sent. If this is not set, then logging messages are +# displayed on the console. If this is set, then messages will be sent to a file with the given name. +# logFile: liquibase.log + + +#### Liquibase Pro Key Information #### +# Learn more, contact support, or get or renew a Pro Key at https://www.liquibase.com/protrial +# liquibase.pro.licensekey: + +#### Liquibase Hub Information #### +# Liquibase Hub is a free secure SaaS portal providing status reporting, monitoring & insights +# into your Liquibase database release automation. +# https://hub.liquibase.com + +## Add your free Hub API key here +# liquibase.hub.apikey: +# liquibase.hub.mode:all + + + + +## Get documentation at docs.liquibase.com ## +## Get certified courses at learn.liquibase.com ## +## Get support at liquibase.com/support ## diff --git a/liquibase-dist/src/main/assembly/assembly-bin.xml b/liquibase-dist/src/main/assembly/assembly-bin.xml index 6255cda5e2b..1370859aad1 100644 --- a/liquibase-dist/src/main/assembly/assembly-bin.xml +++ b/liquibase-dist/src/main/assembly/assembly-bin.xml @@ -47,6 +47,13 @@ **/* + + ${project.basedir}/../liquibase-core/target/classes/liquibase/examples + examples + + **/* + + diff --git a/liquibase-dist/src/main/install4j/liquibase.install4j b/liquibase-dist/src/main/install4j/liquibase.install4j index e13cc83226d..2ed315b28d9 100644 --- a/liquibase-dist/src/main/install4j/liquibase.install4j +++ b/liquibase-dist/src/main/install4j/liquibase.install4j @@ -1,7 +1,7 @@ - + From 44028286c910a9ffda3d488ad9a10042c576492d Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Thu, 9 Dec 2021 16:27:15 -0600 Subject: [PATCH 06/22] LB-2177 Some corrections --- .../examples/sql/liquibase.properties | 2 +- .../examples/sql/blankchangelog.h2.sql | 12 --- .../archive/examples/sql/liquibase.properties | 76 ------------------- .../examples/sql/liquibase.sqlplus.conf | 47 ------------ .../examples/sql/samplechangelog.h2.sql | 23 ------ .../archive/examples/xml/blank.changelog.xml | 18 ----- .../archive/examples/xml/liquibase.properties | 76 ------------------- .../examples/xml/liquibase.sqlplus.conf | 47 ------------ .../archive/examples/xml/sample.changelog.xml | 43 ----------- 9 files changed, 1 insertion(+), 343 deletions(-) delete mode 100644 liquibase-dist/src/main/archive/examples/sql/blankchangelog.h2.sql delete mode 100644 liquibase-dist/src/main/archive/examples/sql/liquibase.properties delete mode 100644 liquibase-dist/src/main/archive/examples/sql/liquibase.sqlplus.conf delete mode 100644 liquibase-dist/src/main/archive/examples/sql/samplechangelog.h2.sql delete mode 100644 liquibase-dist/src/main/archive/examples/xml/blank.changelog.xml delete mode 100644 liquibase-dist/src/main/archive/examples/xml/liquibase.properties delete mode 100644 liquibase-dist/src/main/archive/examples/xml/liquibase.sqlplus.conf delete mode 100644 liquibase-dist/src/main/archive/examples/xml/sample.changelog.xml diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties index 1f30dc71cea..d15b155e6c5 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/liquibase.properties @@ -20,7 +20,7 @@ ## The url H2 example below is relative to 'pwd' resource. #### # Enter the path for your changelog file. -changeLogFile=samplechangelog.h2.sql +changeLogFile=example-changelog.sql #### Enter the Target database 'url' information #### liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev diff --git a/liquibase-dist/src/main/archive/examples/sql/blankchangelog.h2.sql b/liquibase-dist/src/main/archive/examples/sql/blankchangelog.h2.sql deleted file mode 100644 index b82062b1789..00000000000 --- a/liquibase-dist/src/main/archive/examples/sql/blankchangelog.h2.sql +++ /dev/null @@ -1,12 +0,0 @@ ---liquibase formatted sql -/* https://www.liquibase.org/documentation/sql_format.html */ - ---changeset authorname:1 -/* Insert SQL change objects here */ - - ---changeset authorname:2 -/* Insert SQL change objects here */ - - - diff --git a/liquibase-dist/src/main/archive/examples/sql/liquibase.properties b/liquibase-dist/src/main/archive/examples/sql/liquibase.properties deleted file mode 100644 index 1f30dc71cea..00000000000 --- a/liquibase-dist/src/main/archive/examples/sql/liquibase.properties +++ /dev/null @@ -1,76 +0,0 @@ -#### _ _ _ _ -## | | (_) (_) | -## | | _ __ _ _ _ _| |__ __ _ ___ ___ -## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ -## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ -## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| -## | | -## |_| -## -## The liquibase.properties file stores properties which do not change often, -## such as database connection information. Properties stored here save time -## and reduce risk of mistyped command line arguments. -## Learn more: https://www.liquibase.org/documentation/config_properties.html -#### -#### -## Note about relative and absolute paths: -## The liquibase.properties file requires paths for some properties. -## The classpath is the path/to/resources (ex. src/main/resources). -## The changeLogFile path is relative to the classpath. -## The url H2 example below is relative to 'pwd' resource. -#### -# Enter the path for your changelog file. -changeLogFile=samplechangelog.h2.sql - -#### Enter the Target database 'url' information #### -liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev - -# Enter the username for your Target database. -liquibase.command.username: dbuser - -# Enter the password for your Target database. -liquibase.command.password: letmein - -#### Enter the Source Database 'referenceUrl' information #### -## The source database is the baseline or reference against which your target database is compared for diff/diffchangelog commands. - -# Enter URL for the source database -liquibase.command.referenceUrl: jdbc:h2:tcp://localhost:9090/mem:integration - -# Enter the username for your source database -liquibase.command.referenceUsername: dbuser - -# Enter the password for your source database -liquibase.command.referencePassword: letmein - -# Logging Configuration -# logLevel controls the amount of logging information generated. If not set, the default logLevel is INFO. -# Valid values, from least amount of logging to most, are: -# OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL -# If you are having problems, setting the logLevel to DEBUG and re-running the command can be helpful. -# logLevel: DEBUG - -# The logFile property controls where logging messages are sent. If this is not set, then logging messages are -# displayed on the console. If this is set, then messages will be sent to a file with the given name. -# logFile: liquibase.log - - -#### Liquibase Pro Key Information #### -# Learn more, contact support, or get or renew a Pro Key at https://www.liquibase.com/protrial -# liquibase.pro.licensekey: - -#### Liquibase Hub Information #### -# Liquibase Hub is a free secure SaaS portal providing status reporting, monitoring & insights -# into your Liquibase database release automation. -# https://hub.liquibase.com - -## Add your free Hub API key here -# liquibase.hub.apikey: -# liquibase.hub.mode:all - - - - -## Get documentation at docs.liquibase.com ## -## Get certified courses at learn.liquibase.com ## -## Get support at liquibase.com/support ## diff --git a/liquibase-dist/src/main/archive/examples/sql/liquibase.sqlplus.conf b/liquibase-dist/src/main/archive/examples/sql/liquibase.sqlplus.conf deleted file mode 100644 index f6afd2cbcb6..00000000000 --- a/liquibase-dist/src/main/archive/examples/sql/liquibase.sqlplus.conf +++ /dev/null @@ -1,47 +0,0 @@ -#### _ _ _ _ _____ -## | | (_) (_) | | __ \ -## | | _ __ _ _ _ _| |__ __ _ ___ ___ | |__) | __ ___ -## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ | ___/ '__/ _ \ -## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ | | | | | (_) | -## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| |_| |_| \___/ -## | | -## |_| -## -## The liquibase.sqlplus.conf file stores properties which are used during the -## execution of the Oracle SQLPLUS tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html -#### -#### -## Note about relative and absolute paths: -## The liquibase.sqlplus.path must be a valid path to the SQLPlUS executable. -## The liquibase.sqlplus.timeout value can be one of: -## -1 - disable the timeout -## Any integer value > 0 (measured in seconds) -## -#### - -# The full path to the SQLPLUS executable. -# Sample linux path -# liquibase.sqlplus.path=/apps/app/12.2.0.1.0/oracle/product/12.2.0.1.0/client_1/bin/sqlplus -# Sample windows path -# liquibase.sqlplus.path=c:\\oracle\\product\\11.2.0\\client_1\\bin\\sqlplus.exe - -# A valid timeout value for the execution of the SQLPLUS tool -liquibase.sqlplus.timeout=-1 - -# Flag to indicate whether or not to keep the temporary SQL file after execution of SQLPLUS. -# True = keep False = delete (default) -liquibase.sqlplus.keep.temp=true - -# OPTIONAL Flag to designate the location to store temporary SQL file after execution of SQLPLUS. -# Liquibase will attempt to use path exactly as entered, so please ensure it complies with your OS requirements. -# liquibase.sqlplus.keep.temp.path= - -# OPTIONAL Flag to designate the name of temporary SQL file after execution of SQLPLUS. -# Liquibase will attempt to use the name exactly as entered, so please ensure it complies with your OS requirements. -# liquibase.sqlplus.keep.temp.name= - -# OPTIONAL Args to pass directly to SQLPLUS. -# Learn about SQLPLUS args at https://docs.oracle.com/cd/B10501_01/server.920/a90842/ch4.htm -# Note: The delimiter for args is a space eg:" " and not "," or ";" separated. -# liquibase.sqlplus.args= diff --git a/liquibase-dist/src/main/archive/examples/sql/samplechangelog.h2.sql b/liquibase-dist/src/main/archive/examples/sql/samplechangelog.h2.sql deleted file mode 100644 index 5e89d1b7aef..00000000000 --- a/liquibase-dist/src/main/archive/examples/sql/samplechangelog.h2.sql +++ /dev/null @@ -1,23 +0,0 @@ ---liquibase formatted sql - ---changeset your.name:1 -create table person ( - id int primary key, - name varchar(50) not null, - address1 varchar(50), - address2 varchar(50), - city varchar(30) -) - ---changeset your.name:2 -create table company ( - id int primary key, - name varchar(50) not null, - address1 varchar(50), - address2 varchar(50), - city varchar(30) -) - ---changeset other.dev:3 -alter table person add column country varchar(2) - diff --git a/liquibase-dist/src/main/archive/examples/xml/blank.changelog.xml b/liquibase-dist/src/main/archive/examples/xml/blank.changelog.xml deleted file mode 100644 index fc9b1d763d1..00000000000 --- a/liquibase-dist/src/main/archive/examples/xml/blank.changelog.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - diff --git a/liquibase-dist/src/main/archive/examples/xml/liquibase.properties b/liquibase-dist/src/main/archive/examples/xml/liquibase.properties deleted file mode 100644 index fa7fb0ff901..00000000000 --- a/liquibase-dist/src/main/archive/examples/xml/liquibase.properties +++ /dev/null @@ -1,76 +0,0 @@ -#### _ _ _ _ -## | | (_) (_) | -## | | _ __ _ _ _ _| |__ __ _ ___ ___ -## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ -## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ -## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| -## | | -## |_| -## -## The liquibase.properties file stores properties which do not change often, -## such as database connection information. Properties stored here save time -## and reduce risk of mistyped command line arguments. -## Learn more: https://www.liquibase.org/documentation/config_properties.html -#### -#### -## Note about relative and absolute paths: -## The liquibase.properties file requires paths for some properties. -## The classpath is the path/to/resources (ex. src/main/resources). -## The changeLogFile path is relative to the classpath. -## The url H2 example below is relative to 'pwd' resource. -#### -# Enter the path for your changelog file. -changeLogFile=sample.changelog.xml - -#### Enter the Target database 'url' information #### -liquibase.command.url=jdbc:h2:tcp://localhost:9090/mem:dev - -# Enter the username for your Target database. -liquibase.command.username: dbuser - -# Enter the password for your Target database. -liquibase.command.password: letmein - -#### Enter the Source Database 'referenceUrl' information #### -## The source database is the baseline or reference against which your target database is compared for diff/diffchangelog commands. - -# Enter URL for the source database -liquibase.command.referenceUrl: jdbc:h2:tcp://localhost:9090/mem:integration - -# Enter the username for your source database -liquibase.command.referenceUsername: dbuser - -# Enter the password for your source database -liquibase.command.referencePassword: letmein - -# Logging Configuration -# logLevel controls the amount of logging information generated. If not set, the default logLevel is INFO. -# Valid values, from least amount of logging to most, are: -# OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL -# If you are having problems, setting the logLevel to DEBUG and re-running the command can be helpful. -# logLevel: DEBUG - -# The logFile property controls where logging messages are sent. If this is not set, then logging messages are -# displayed on the console. If this is set, then messages will be sent to a file with the given name. -# logFile: liquibase.log - - -#### Liquibase Pro Key Information #### -# Learn more, contact support, or get or renew a Pro Key at https://www.liquibase.com/protrial -# liquibase.pro.licensekey: - -#### Liquibase Hub Information #### -# Liquibase Hub is a free secure SaaS portal providing status reporting, monitoring & insights -# into your Liquibase database release automation. -# https://hub.liquibase.com - -## Add your free Hub API key here -# liquibase.hub.apikey: -# liquibase.hub.mode:all - - - - -## Get documentation at docs.liquibase.com ## -## Get certified courses at learn.liquibase.com ## -## Get support at liquibase.com/support ## diff --git a/liquibase-dist/src/main/archive/examples/xml/liquibase.sqlplus.conf b/liquibase-dist/src/main/archive/examples/xml/liquibase.sqlplus.conf deleted file mode 100644 index f6afd2cbcb6..00000000000 --- a/liquibase-dist/src/main/archive/examples/xml/liquibase.sqlplus.conf +++ /dev/null @@ -1,47 +0,0 @@ -#### _ _ _ _ _____ -## | | (_) (_) | | __ \ -## | | _ __ _ _ _ _| |__ __ _ ___ ___ | |__) | __ ___ -## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ | ___/ '__/ _ \ -## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ | | | | | (_) | -## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| |_| |_| \___/ -## | | -## |_| -## -## The liquibase.sqlplus.conf file stores properties which are used during the -## execution of the Oracle SQLPLUS tool. -## Learn more: https://www.liquibase.org/documentation/config_properties.html -#### -#### -## Note about relative and absolute paths: -## The liquibase.sqlplus.path must be a valid path to the SQLPlUS executable. -## The liquibase.sqlplus.timeout value can be one of: -## -1 - disable the timeout -## Any integer value > 0 (measured in seconds) -## -#### - -# The full path to the SQLPLUS executable. -# Sample linux path -# liquibase.sqlplus.path=/apps/app/12.2.0.1.0/oracle/product/12.2.0.1.0/client_1/bin/sqlplus -# Sample windows path -# liquibase.sqlplus.path=c:\\oracle\\product\\11.2.0\\client_1\\bin\\sqlplus.exe - -# A valid timeout value for the execution of the SQLPLUS tool -liquibase.sqlplus.timeout=-1 - -# Flag to indicate whether or not to keep the temporary SQL file after execution of SQLPLUS. -# True = keep False = delete (default) -liquibase.sqlplus.keep.temp=true - -# OPTIONAL Flag to designate the location to store temporary SQL file after execution of SQLPLUS. -# Liquibase will attempt to use path exactly as entered, so please ensure it complies with your OS requirements. -# liquibase.sqlplus.keep.temp.path= - -# OPTIONAL Flag to designate the name of temporary SQL file after execution of SQLPLUS. -# Liquibase will attempt to use the name exactly as entered, so please ensure it complies with your OS requirements. -# liquibase.sqlplus.keep.temp.name= - -# OPTIONAL Args to pass directly to SQLPLUS. -# Learn about SQLPLUS args at https://docs.oracle.com/cd/B10501_01/server.920/a90842/ch4.htm -# Note: The delimiter for args is a space eg:" " and not "," or ";" separated. -# liquibase.sqlplus.args= diff --git a/liquibase-dist/src/main/archive/examples/xml/sample.changelog.xml b/liquibase-dist/src/main/archive/examples/xml/sample.changelog.xml deleted file mode 100644 index cee6908804b..00000000000 --- a/liquibase-dist/src/main/archive/examples/xml/sample.changelog.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 3432f049f7166fa6dbe79f4207cb61d12d7e8b53 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Thu, 9 Dec 2021 16:35:11 -0600 Subject: [PATCH 07/22] LB-2177 Remove changelogId from example --- .../resources/liquibase/examples/yaml/example-changelog.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml index 0ca1741a930..1334cb9795c 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml @@ -1,5 +1,4 @@ databaseChangeLog: -- changeLogId: 455d447e-d2c9-42f1-b283-0cc524934a51 - changeSet: id: 1 author: your.name From a69006ce0fcfc3e33a993e854cb78cebe5846ff1 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Fri, 10 Dec 2021 11:32:07 -0600 Subject: [PATCH 08/22] LB-2177 More files --- .../examples/json/blank.changelog.json | 18 ++++++++++++++++++ ...{blankchangelog.sql => blank.changelog.sql} | 0 .../liquibase/examples/xml/blank.changelog.xml | 4 ++-- .../examples/yaml/blank.changelog.yaml | 12 ++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 liquibase-core/src/main/resources/liquibase/examples/json/blank.changelog.json rename liquibase-core/src/main/resources/liquibase/examples/sql/{blankchangelog.sql => blank.changelog.sql} (100%) create mode 100644 liquibase-core/src/main/resources/liquibase/examples/yaml/blank.changelog.yaml diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/blank.changelog.json b/liquibase-core/src/main/resources/liquibase/examples/json/blank.changelog.json new file mode 100644 index 00000000000..d912de64160 --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/json/blank.changelog.json @@ -0,0 +1,18 @@ +{ "databaseChangeLog": [ + "changeset": { + "id": "1", + "author": "your.name", + "changes": [ + { + } + ] + }, + "changeset": { + "id": "2", + "author": "your.name", + "changes": [ + { + } + ] + } +]} diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/blankchangelog.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/blank.changelog.sql similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/sql/blankchangelog.sql rename to liquibase-core/src/main/resources/liquibase/examples/sql/blank.changelog.sql diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml b/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml index fc9b1d763d1..61e339e5c36 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml +++ b/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml @@ -8,11 +8,11 @@ http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.6.xsd "> - + - + diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/blank.changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank.changelog.yaml new file mode 100644 index 00000000000..2a45be37f4c --- /dev/null +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank.changelog.yaml @@ -0,0 +1,12 @@ +databaseChangeLog: +- changeSet: + id: 1 + author: your.name + changes: + # Insert Yaml change objects here https://www.liquibase.org/documentation/xml_format.html + +- changeSet: + id: 2 + author: your.name + changes: + # Insert Yaml change objects here https://www.liquibase.org/documentation/xml_format.html From 145ad997db6bff86e0631508a9285c9aad1bb46f Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Mon, 13 Dec 2021 09:50:52 -0600 Subject: [PATCH 09/22] Fixed issues with sample JSON changelog DAT-8766 --- .../examples/json/example-changelog.json | 221 +++++++++--------- 1 file changed, 110 insertions(+), 111 deletions(-) diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json b/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json index 3cef3ef10b4..de1539e031d 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json +++ b/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json @@ -1,120 +1,119 @@ { "databaseChangeLog": [ - "changeset": { - "id": "1", - "author": "your.name", - "changes": [ + { + "changeSet": { + "id": "1", + "author": "your.name", + "changes": [ { - "createTable": - { - "tablename": "person", - "columns": [ - { - "column": { - "name": "id", - "type": "int", - "autoincrement": true, - "constraints": { - "primarykey": true, - "nullable": false - } - } - }, - { - "column": { - "name": "name", - "type": "varchar(50)" - } - }, - { - "column": { - "name": "addresss1", - "type": "varchar(50)" - } - }, - { - "column": { - "name": "addresss2", - "type": "varchar(50)" - } - }, - { - "column": { - "name": "city", - "type": "varchar(30)" - } - } - ] - } + "createTable": { + "tablename": "person", + "columns": [ + { + "column": { + "name": "id", + "type": "int", + "autoincrement": true, + "constraints": { + "primarykey": true, + "nullable": false + } + } + }, + { + "column": { + "name": "name", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss1", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss2", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "city", + "type": "varchar(30)" + } + } + ] + } } - ] - }, - "changeset": { - "id": "2", - "author": "your.name", - "changes": [ + ] + }, + "changeSet": { + "id": "2", + "author": "your.name", + "changes": [ { - "createTable": - { - "tablename": "company", - "columns": [ - { - "column": { - "name": "id", - "type": "int", - "autoincrement": true, - "constraints": { - "primarykey": true, - "nullable": false - } - } - }, - { - "column": { - "name": "name", - "type": "varchar(50)" - } - }, - { - "column": { - "name": "addresss1", - "type": "varchar(50)" - } - }, - { - "column": { - "name": "addresss2", - "type": "varchar(50)" - } - }, - { - "column": { - "name": "city", - "type": "varchar(30)" - } - } - ] - } + "createTable": { + "tablename": "company", + "columns": [ + { + "column": { + "name": "id", + "type": "int", + "autoincrement": true, + "constraints": { + "primarykey": true, + "nullable": false + } + } + }, + { + "column": { + "name": "name", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss1", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "addresss2", + "type": "varchar(50)" + } + }, + { + "column": { + "name": "city", + "type": "varchar(30)" + } + } + ] + } } - ] - }, - "changeset": { - "id": "3", - "author": "your.name", - "changes": [ + ] + }, + "changeSet": { + "id": "3", + "author": "your.name", + "changes": [ { - "addColumn": - { - "tablename": "company", - "columns": [ - { - "column": { - "name": "country", - "type": "varchar(2)" - } - } - ] - } + "addColumn": { + "tableName": "company", + "columns": [ + { + "column": { + "name": "country", + "type": "varchar(2)" + } + } + ] + } } - ] + ] + } } ]} From b55b75668fbc7c18c95f3f2555e9a2d81387ad5a Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Mon, 13 Dec 2021 10:36:38 -0600 Subject: [PATCH 10/22] Another sample changelog modification DAT-8601 --- .../examples/json/example-changelog.json | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json b/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json index de1539e031d..e502227fca6 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json +++ b/liquibase-core/src/main/resources/liquibase/examples/json/example-changelog.json @@ -6,13 +6,13 @@ "changes": [ { "createTable": { - "tablename": "person", + "tableName": "person", "columns": [ { "column": { "name": "id", "type": "int", - "autoincrement": true, + "autoIncrement": true, "constraints": { "primarykey": true, "nullable": false @@ -45,22 +45,23 @@ } ] } - } - ] - }, + }] + } + }, + { "changeSet": { "id": "2", "author": "your.name", "changes": [ { "createTable": { - "tablename": "company", + "tableName": "company", "columns": [ { "column": { "name": "id", "type": "int", - "autoincrement": true, + "autoIncrement": true, "constraints": { "primarykey": true, "nullable": false @@ -93,9 +94,10 @@ } ] } - } - ] - }, + }] + } + }, + { "changeSet": { "id": "3", "author": "your.name", @@ -112,8 +114,7 @@ } ] } - } - ] + }] } } ]} From 6b406df79773b53fc3c0d8e685bc362b2b145541 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Tue, 14 Dec 2021 09:58:42 -0600 Subject: [PATCH 11/22] Revert "Move interactive prompting logic into core module (DAT-8642) (#2255)" This reverts commit 2c70056777f6753a1d685f663da31dbb91eb1c11. --- .../AbstractCommandLineValueGetter.java | 136 ------------------ .../ui/interactive/DynamicRuleParameter.java | 65 --------- .../IInteractivelyPromptableEnum.java | 29 ---- ...ractivePromptableCustomizationWrapper.java | 69 --------- 4 files changed, 299 deletions(-) delete mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java delete mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java delete mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java delete mode 100644 liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java b/liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java deleted file mode 100644 index 864add7e9b9..00000000000 --- a/liquibase-core/src/main/java/liquibase/ui/interactive/AbstractCommandLineValueGetter.java +++ /dev/null @@ -1,136 +0,0 @@ -package liquibase.ui.interactive; - -import liquibase.Scope; -import liquibase.ui.InputHandler; - -import java.util.List; - -/** - * This class represents the basis for prompts to the user to input values, and should be used as part of the process - * of obtaining user input for quality checks. - * @param the type the user is expected to enter - */ -public abstract class AbstractCommandLineValueGetter { - - /** - * The type of the value that will be obtained. - */ - private final Class clazz; - - /** - * Create a new value getter. - * @param clazz the type of the value that will be obtained - */ - public AbstractCommandLineValueGetter(Class clazz) { - this.clazz = clazz; - } - - /** - * Prompt the user to enter a value for a parameter, and include the existing value in the prompt. - * @param parameter the parameter to obtain a value for - * @param newParameterValues a list of the values that have already been entered by the user during this interactive CLI parameter prompting situation - * @return the value entered by the user - */ - public final T prompt(InteractivePromptableCustomizationWrapper parameter, List newParameterValues, Object currentValue) { - // determine which value should be displayed in square brackets as the value that will be selected if user presses enter - Object valueToPromptAsDefault; - if (currentValue != null) { - /* - * The value is being converted here, because enum types get read from the check settings file as strings. - * As a result, the default value and current value (which should be the same type), are not; the default - * value would be an enum and the current value would be a string. - */ - try { - valueToPromptAsDefault = convert((String) currentValue); - } catch (Exception e) { - valueToPromptAsDefault = currentValue; - } - } else { - valueToPromptAsDefault = parameter.getDefaultValue(); - } - - // assume the user just hit enter to accept the default and revalidate it, since hitting enter to accept the - // default skips the validation logic in ConsoleUIService. Reprompt endlessly until a valid value is entered. - T prompt = null; - boolean valid = false; - while (!valid && (prompt == null || prompt.equals(valueToPromptAsDefault))) { - prompt = doPrompt(parameter, newParameterValues, valueToPromptAsDefault, (currentValue != null || parameter.getDefaultValue() != null)); - - try { - valid = doValidate(parameter, newParameterValues, prompt); - } catch (IllegalArgumentException e) { - Scope.getCurrentScope().getUI().sendErrorMessage("Invalid value: '" + prompt + "': " + e.getMessage()); - } - } - return prompt; - } - - private T doPrompt(InteractivePromptableCustomizationWrapper parameter, List newParameterValues, Object valueToPromptAsDefault, boolean shouldAllowEmptyValues) { - return Scope.getCurrentScope().getUI().prompt(getMessage(parameter), (T) valueToPromptAsDefault, new InputHandler() { - @Override - public T parseInput(String input, Class type) throws IllegalArgumentException { - T convert; - try { - convert = AbstractCommandLineValueGetter.this.convert(input); - } catch (Exception e) { - if (e.getMessage() != null) { - throw new IllegalArgumentException( - String.format("Invalid value: '%s': %s", input, e.getMessage()), e); - } - throw new IllegalArgumentException(e); - } - - try { - if (!doValidate(parameter, newParameterValues, convert)) { - throw new IllegalArgumentException("The supplied value is not valid."); - } - } catch (Exception e) { - if (e.getMessage() != null) { - throw new IllegalArgumentException( - String.format("Invalid value: '%s': %s", input, e.getMessage()), e); - } - throw new IllegalArgumentException( - String.format("Invalid value: '%s': The supplied value is not valid.", input), e); - } - return convert; - } - - @Override - public boolean shouldAllowEmptyInput() { - // We do not allow empty input, because as of right now, all parameters require values. In the future, - // there may be parameters which permit empty values, which would need to tie in here. - return shouldAllowEmptyValues; - } - }, clazz); - } - - private boolean doValidate(InteractivePromptableCustomizationWrapper parameter, List newParameterValues, T convert) throws IllegalArgumentException { - if (parameter.getValidationCallbackOverride() != null) { - return parameter.getValidationCallbackOverride().apply(convert, newParameterValues); - } else { - return AbstractCommandLineValueGetter.this.validate(convert); - } - } - - /** - * Generate the prompt message. - * @param parameter the parameter to prompt for - * @return the message - */ - private String getMessage(InteractivePromptableCustomizationWrapper parameter) { - return parameter.getParameter().getUiMessage() + " (options: " + parameter.getParameter().getOptions() + ")"; - } - - /** - * Given the input from the user, after being converted, validate it. - * @return true if it is valid - */ - public abstract boolean validate(T input); - - /** - * Given the raw input string from the user, convert it to the right type. - * @param input the raw input string from the prompt - * @return the converted input - */ - public abstract T convert(String input); -} diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java b/liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java deleted file mode 100644 index 16023baf104..00000000000 --- a/liquibase-core/src/main/java/liquibase/ui/interactive/DynamicRuleParameter.java +++ /dev/null @@ -1,65 +0,0 @@ -package liquibase.ui.interactive; - - -import java.util.Objects; - - -public class DynamicRuleParameter { - - /** - * The actual underlying DynamicRuleParameterEnum that corresponds to this value. We store the parameter as a string, - * because different versions of Liquibase might not contain the enum that the rule requires. We want to be able to - * parse newer conf files with older versions of Liquibase, without a SnakeYaml error that it cannot find the enum - * value. - */ - private String parameter; - private Object value; - - /** - * Constructor for SnakeYaml - */ - public DynamicRuleParameter() { - } - - public DynamicRuleParameter(IInteractivelyPromptableEnum parameter, Object value) { - Objects.requireNonNull(parameter); - this.parameter = parameter.toString(); - this.value = value; - } - - public DynamicRuleParameter(String parameter, Object value) { - Objects.requireNonNull(parameter); - this.parameter = parameter; - this.value = value; - } - - public String getParameter() { - return parameter; - } - - public void setParameter(String parameter) { - this.parameter = parameter; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DynamicRuleParameter that = (DynamicRuleParameter) o; - return Objects.equals(parameter, that.parameter) && value.equals(that.value); - } - - @Override - public int hashCode() { - return Objects.hash(parameter, value); - } -} - diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java b/liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java deleted file mode 100644 index ed76c26679b..00000000000 --- a/liquibase-core/src/main/java/liquibase/ui/interactive/IInteractivelyPromptableEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package liquibase.ui.interactive; - - -public interface IInteractivelyPromptableEnum { - /** - * Description of the parameter to be used in the UI output. - */ - String getDescription(); - - /** - * The default value of the parameter if the parameter has not been customized. - */ - Object getDefaultValue(); - - /** - * The implementation of the value getter that will be used to prompt the user to input a value. - */ - AbstractCommandLineValueGetter getInteractiveCommandLineValueGetter(); - - /** - * Parameter message to be used in the UI output. - */ - String getUiMessage(); - - /* - * Possible options for this parameter - */ - String getOptions(); -} diff --git a/liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java b/liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java deleted file mode 100644 index be0659ae562..00000000000 --- a/liquibase-core/src/main/java/liquibase/ui/interactive/InteractivePromptableCustomizationWrapper.java +++ /dev/null @@ -1,69 +0,0 @@ -package liquibase.ui.interactive; - - -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * This class exists to wrap the parameter enum so that individual usages can provide specific - * overrides of the logic defined in the enum class. You should access the underlying parameter as little as possible - * and instead, access it using getter wrapper methods in this class. That will allow future developers to specify - * custom overrides for each rule (for example, overriding the default value for a specific usage without - * affecting all others). - */ -public class InteractivePromptableCustomizationWrapper { - private final IInteractivelyPromptableEnum parameter; - private final BiFunction, Boolean> validationCallbackOverride; - private final Function, Boolean> shouldPrompt; - - public InteractivePromptableCustomizationWrapper(IInteractivelyPromptableEnum parameter) { - this.parameter = parameter; - this.validationCallbackOverride = null; - this.shouldPrompt = null; - } - - public InteractivePromptableCustomizationWrapper(IInteractivelyPromptableEnum parameter, BiFunction, Boolean> validationCallbackOverride, Function, Boolean> shouldPrompt) { - this.parameter = parameter; - this.validationCallbackOverride = validationCallbackOverride; - this.shouldPrompt = shouldPrompt; - } - - public Object getDefaultValue() { - return parameter.getDefaultValue(); - } - - public IInteractivelyPromptableEnum getParameter() { - return parameter; - } - - public AbstractCommandLineValueGetter getInteractiveCommandLineValueGetter() { - return parameter.getInteractiveCommandLineValueGetter(); - } - - public BiFunction, Boolean> getValidationCallbackOverride() { - return validationCallbackOverride; - } - - public Function, Boolean> getShouldPrompt() { - return shouldPrompt; - } - - @Override - public String toString() { - return getParameter().toString(); - } - - /** - * Determine if the rule parameter should be prompted for in a checks customize scenario. - * @param existingNewValues the values already provided in the checks customize session - * @return true if the prompt should occur for this parameter, false if not - */ - public boolean shouldPrompt(List existingNewValues) { - boolean resp = true; - if (shouldPrompt != null) { - resp = shouldPrompt.apply(existingNewValues); - } - return resp; - } -} From ce9e19af23cdf9c66c085ba647bc3fb82ea3e714 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Tue, 14 Dec 2021 22:26:50 -0600 Subject: [PATCH 12/22] Modified yaml sample changelog Test fix DAT-8724 --- .../resources/liquibase/examples/yaml/example-changelog.yaml | 2 +- .../extension/testing/setup/SetupCleanResources.groovy | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml index 1334cb9795c..e102c5b95dc 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changelog.yaml @@ -43,5 +43,5 @@ databaseChangeLog: tableName: company columns: - column: - name: id + name: country type: varchar(2) diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy index beddeb51ef7..20db33ac81b 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCleanResources.groovy @@ -48,6 +48,9 @@ class SetupCleanResources extends TestSetup { f = new File(url.toURI()) } + if (! f.exists()) { + continue + } if (f.isFile()) { f.delete() } else { From 5fa3257137d9cac7802867294ce73c73c504907f Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Wed, 15 Dec 2021 08:12:36 -0600 Subject: [PATCH 13/22] when reprompting for input after an invalid value, show the default value in brackets --- liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java b/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java index 5e29c6c4ff5..ef4b7637c63 100644 --- a/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java +++ b/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java @@ -113,7 +113,7 @@ public T prompt(String prompt, T valueIfNoEntry, InputHandler inputHandle message = "Invalid value: \"" + input + "\""; } this.sendMessage(message); - this.sendMessage(prompt + ": "); + this.sendMessage(initialMessage + ": "); } } } From 70e11e78880861ecf985f411088fe766366a0b4c Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Wed, 15 Dec 2021 08:14:25 -0600 Subject: [PATCH 14/22] interactively prompt for input from the init project command --- .../commandline/LiquibaseCommandLine.java | 3 +- .../java/liquibase/command/CommandScope.java | 7 +++++ .../InteractivePromptingValueProvider.java | 30 +++++++++++++++++++ .../liquibase/ui/ConsoleUIServiceTest.groovy | 2 +- .../testing/command/CommandTests.groovy | 2 ++ 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java diff --git a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java index 05f62f98c51..c5c236c106f 100644 --- a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java +++ b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java @@ -8,6 +8,7 @@ import liquibase.configuration.ConfiguredValue; import liquibase.configuration.LiquibaseConfiguration; import liquibase.configuration.core.DefaultsFileValueProvider; +import liquibase.configuration.core.InteractivePromptingValueProvider; import liquibase.exception.CommandLineParsingException; import liquibase.exception.CommandValidationException; import liquibase.hub.HubConfiguration; @@ -467,7 +468,7 @@ public int getPrecedence() { } else { Scope.getCurrentScope().getLog(getClass()).fine("Cannot find local defaultsFile " + defaultsFile.getAbsolutePath()); } - + liquibaseConfiguration.registerProvider(new InteractivePromptingValueProvider()); return returnList; } diff --git a/liquibase-core/src/main/java/liquibase/command/CommandScope.java b/liquibase-core/src/main/java/liquibase/command/CommandScope.java index 04bd62f9881..ff6b1fef72b 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandScope.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandScope.java @@ -58,6 +58,13 @@ public CommandDefinition getCommand() { return commandDefinition; } + /** + * Returns the complete config prefix (without a trailing period) for the command in this scope. + * @return + */ + public String getCompleteConfigPrefix() { + return completeConfigPrefix; + } /** * Adds the given key/value pair to the stored argument data. diff --git a/liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java new file mode 100644 index 00000000000..05e942e4068 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java @@ -0,0 +1,30 @@ +package liquibase.configuration.core; + +import liquibase.configuration.AbstractMapConfigurationValueProvider; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * This value provider handles values obtained during interactive CLI prompting. + */ +public class InteractivePromptingValueProvider extends AbstractMapConfigurationValueProvider { + + public static final SortedMap values = new TreeMap<>(); + + @Override + protected Map getMap() { + return values; + } + + @Override + protected String getSourceDescription() { + return "CLI interactive prompts"; + } + + @Override + public int getPrecedence() { + return 500; + } +} \ No newline at end of file diff --git a/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy b/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy index ce4702e439c..8c8001c78e8 100644 --- a/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy @@ -29,7 +29,7 @@ class ConsoleUIServiceTest extends Specification { "" | null | null | "Prompt here: " | String "x" | null | "x" | "Prompt here: " | String "1234" | null | 1234 | "Prompt here: " | Integer - ["x", "1234"] as String[] | 0 | 1234 | "Prompt here [0]: \nInvalid value: 'x': For input string: \"x\"\nPrompt here: " | Integer + ["x", "1234"] as String[] | 0 | 1234 | "Prompt here [0]: \nInvalid value: 'x': For input string: \"x\"\nPrompt here [0]:" | Integer "true" | false | true | "Prompt here [false]: " | Boolean "false" | false | false | "Prompt here [false]: " | Boolean } diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index b61aad4ffdc..5c18de48cde 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -15,6 +15,7 @@ import liquibase.command.core.InternalSnapshotCommandStep import liquibase.configuration.AbstractMapConfigurationValueProvider import liquibase.configuration.ConfigurationValueProvider import liquibase.configuration.LiquibaseConfiguration +import liquibase.configuration.core.InteractivePromptingValueProvider import liquibase.database.Database import liquibase.database.DatabaseFactory import liquibase.database.jvm.JdbcConnection @@ -86,6 +87,7 @@ class CommandTests extends Specification { } Scope.currentScope.getSingleton(LiquibaseConfiguration).registerProvider(propertiesProvider) + Scope.currentScope.getSingleton(LiquibaseConfiguration).registerProvider(new InteractivePromptingValueProvider()) } def cleanup() { From e8ed4070a24ad608397ea1a98e42d4216e96a754 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Wed, 15 Dec 2021 09:32:08 -0600 Subject: [PATCH 15/22] Renamed example files DAT-8724 --- .../examples/json/{blank.changelog.json => blank-changelog.json} | 0 .../json/{example-changeset.json => example-changeset-json.txt} | 0 .../examples/sql/{blank.changelog.sql => blank-changelog.sql} | 0 .../sql/{example-changeset.sql => example-changeset-sql.txt} | 0 .../examples/xml/{blank.changelog.xml => blank-changelog.xml} | 0 .../xml/{example-changeset.xml => example-changeset-xml.txt} | 0 .../examples/yaml/{blank.changelog.yaml => blank-changelog.yaml} | 0 .../yaml/{example-changeset.yaml => example-changeset-yaml.txt} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename liquibase-core/src/main/resources/liquibase/examples/json/{blank.changelog.json => blank-changelog.json} (100%) rename liquibase-core/src/main/resources/liquibase/examples/json/{example-changeset.json => example-changeset-json.txt} (100%) rename liquibase-core/src/main/resources/liquibase/examples/sql/{blank.changelog.sql => blank-changelog.sql} (100%) rename liquibase-core/src/main/resources/liquibase/examples/sql/{example-changeset.sql => example-changeset-sql.txt} (100%) rename liquibase-core/src/main/resources/liquibase/examples/xml/{blank.changelog.xml => blank-changelog.xml} (100%) rename liquibase-core/src/main/resources/liquibase/examples/xml/{example-changeset.xml => example-changeset-xml.txt} (100%) rename liquibase-core/src/main/resources/liquibase/examples/yaml/{blank.changelog.yaml => blank-changelog.yaml} (100%) rename liquibase-core/src/main/resources/liquibase/examples/yaml/{example-changeset.yaml => example-changeset-yaml.txt} (100%) diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/blank.changelog.json b/liquibase-core/src/main/resources/liquibase/examples/json/blank-changelog.json similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/json/blank.changelog.json rename to liquibase-core/src/main/resources/liquibase/examples/json/blank-changelog.json diff --git a/liquibase-core/src/main/resources/liquibase/examples/json/example-changeset.json b/liquibase-core/src/main/resources/liquibase/examples/json/example-changeset-json.txt similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/json/example-changeset.json rename to liquibase-core/src/main/resources/liquibase/examples/json/example-changeset-json.txt diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/blank.changelog.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/blank-changelog.sql similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/sql/blank.changelog.sql rename to liquibase-core/src/main/resources/liquibase/examples/sql/blank-changelog.sql diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset.sql b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset-sql.txt similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset.sql rename to liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset-sql.txt diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml b/liquibase-core/src/main/resources/liquibase/examples/xml/blank-changelog.xml similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/xml/blank.changelog.xml rename to liquibase-core/src/main/resources/liquibase/examples/xml/blank-changelog.xml diff --git a/liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset.xml b/liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset-xml.txt similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset.xml rename to liquibase-core/src/main/resources/liquibase/examples/xml/example-changeset-xml.txt diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/blank.changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/yaml/blank.changelog.yaml rename to liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset-yaml.txt similarity index 100% rename from liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset.yaml rename to liquibase-core/src/main/resources/liquibase/examples/yaml/example-changeset-yaml.txt From d985c5371a4beb3960cf06a382d6eed2597e942f Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Wed, 15 Dec 2021 14:54:41 -0600 Subject: [PATCH 16/22] Fix doc issues in files DAT-8724 --- .../liquibase/examples/sql/example-changeset-sql.txt | 2 +- .../resources/liquibase/examples/yaml/blank-changelog.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset-sql.txt b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset-sql.txt index 72fd788ec8e..88f181639b6 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset-sql.txt +++ b/liquibase-core/src/main/resources/liquibase/examples/sql/example-changeset-sql.txt @@ -1,4 +1,4 @@ -(example-changeset.sql) +(example-changeset-sql.txt) --changeset dev:1 create table test1( diff --git a/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml index 2a45be37f4c..771e1911fde 100644 --- a/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml +++ b/liquibase-core/src/main/resources/liquibase/examples/yaml/blank-changelog.yaml @@ -3,10 +3,10 @@ databaseChangeLog: id: 1 author: your.name changes: - # Insert Yaml change objects here https://www.liquibase.org/documentation/xml_format.html + # Insert Yaml change objects here https://www.liquibase.org/documentation/yaml_format.html - changeSet: id: 2 author: your.name changes: - # Insert Yaml change objects here https://www.liquibase.org/documentation/xml_format.html + # Insert Yaml change objects here https://www.liquibase.org/documentation/yaml_format.html From 82581561c9c7424bad791782093b815e7f37d402 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Mon, 20 Dec 2021 10:32:35 -0600 Subject: [PATCH 17/22] Fix prompt bug and add "run after method" logic to command tests (DAT-8804) (#2276) Add "run after method" callable to CommandTests.groovy Fix a bug where reprompting for user input after receiving invalid input does not display the default value in brackets --- .../src/main/java/liquibase/command/CommandScope.java | 7 +++++++ .../src/main/java/liquibase/ui/ConsoleUIService.java | 2 +- .../groovy/liquibase/ui/ConsoleUIServiceTest.groovy | 2 +- .../extension/testing/command/CommandTests.groovy | 11 +++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/command/CommandScope.java b/liquibase-core/src/main/java/liquibase/command/CommandScope.java index 04bd62f9881..ff6b1fef72b 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandScope.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandScope.java @@ -58,6 +58,13 @@ public CommandDefinition getCommand() { return commandDefinition; } + /** + * Returns the complete config prefix (without a trailing period) for the command in this scope. + * @return + */ + public String getCompleteConfigPrefix() { + return completeConfigPrefix; + } /** * Adds the given key/value pair to the stored argument data. diff --git a/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java b/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java index 5e29c6c4ff5..ef4b7637c63 100644 --- a/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java +++ b/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java @@ -113,7 +113,7 @@ public T prompt(String prompt, T valueIfNoEntry, InputHandler inputHandle message = "Invalid value: \"" + input + "\""; } this.sendMessage(message); - this.sendMessage(prompt + ": "); + this.sendMessage(initialMessage + ": "); } } } diff --git a/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy b/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy index ce4702e439c..8c8001c78e8 100644 --- a/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/ui/ConsoleUIServiceTest.groovy @@ -29,7 +29,7 @@ class ConsoleUIServiceTest extends Specification { "" | null | null | "Prompt here: " | String "x" | null | "x" | "Prompt here: " | String "1234" | null | 1234 | "Prompt here: " | Integer - ["x", "1234"] as String[] | 0 | 1234 | "Prompt here [0]: \nInvalid value: 'x': For input string: \"x\"\nPrompt here: " | Integer + ["x", "1234"] as String[] | 0 | 1234 | "Prompt here [0]: \nInvalid value: 'x': For input string: \"x\"\nPrompt here [0]:" | Integer "true" | false | true | "Prompt here [false]: " | Boolean "false" | false | false | "Prompt here [false]: " | Boolean } diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index b61aad4ffdc..45aeadbbcc5 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -42,6 +42,7 @@ import org.junit.ComparisonFailure import spock.lang.Specification import spock.lang.Unroll +import java.util.concurrent.Callable import java.util.logging.Level import java.util.regex.Pattern @@ -290,6 +291,10 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} } return } + } finally { + if (testDef.commandTestDefinition.afterMethodInvocation != null) { + testDef.commandTestDefinition.afterMethodInvocation.call() + } } } as Scope.ScopedRunnerWithReturn) @@ -552,6 +557,12 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} List runTests = new ArrayList<>() String signature + /** + * An optional method that will be called after the execution of each run command. This is executed within + * the same scope as the command that is run for the test. This method will always be called, regardless of + * exceptions thrown from within the test. + */ + Callable afterMethodInvocation void run(@DelegatesTo(RunTestDefinition) Closure testClosure) { run(null, testClosure) From 0e4d091d0f3583ddb978675dded75a6305e973ab Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Wed, 22 Dec 2021 09:04:30 -0600 Subject: [PATCH 18/22] Added output capture to TestUI class DAT-8784 --- .../liquibase/extension/testing/command/CommandTests.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index 924bc905eff..33cc999604a 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -1079,6 +1079,7 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} @Override def T prompt(String prompt, T valueIfNoEntry, InputHandler inputHandler, Class type) { + this.sendMessage(prompt + ": "); return valueIfNoEntry } From 02472bb8c71ff257153f559fe0e4c22807800135 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Thu, 23 Dec 2021 10:05:35 -0600 Subject: [PATCH 19/22] Remove unused file DAT-8784 --- .../InteractivePromptingValueProvider.java | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java diff --git a/liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java deleted file mode 100644 index 05e942e4068..00000000000 --- a/liquibase-core/src/main/java/liquibase/configuration/core/InteractivePromptingValueProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package liquibase.configuration.core; - -import liquibase.configuration.AbstractMapConfigurationValueProvider; - -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -/** - * This value provider handles values obtained during interactive CLI prompting. - */ -public class InteractivePromptingValueProvider extends AbstractMapConfigurationValueProvider { - - public static final SortedMap values = new TreeMap<>(); - - @Override - protected Map getMap() { - return values; - } - - @Override - protected String getSourceDescription() { - return "CLI interactive prompts"; - } - - @Override - public int getPrecedence() { - return 500; - } -} \ No newline at end of file From 8fb819cc03a5217a22b37095fb50bd4abe5ff735 Mon Sep 17 00:00:00 2001 From: Surya Aki Date: Thu, 23 Dec 2021 10:36:33 -0600 Subject: [PATCH 20/22] remove InteractivePromptingValueProvider --- .../liquibase/integration/commandline/LiquibaseCommandLine.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java index c5c236c106f..f5a1e3065a0 100644 --- a/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java +++ b/liquibase-cli/src/main/java/liquibase/integration/commandline/LiquibaseCommandLine.java @@ -8,7 +8,6 @@ import liquibase.configuration.ConfiguredValue; import liquibase.configuration.LiquibaseConfiguration; import liquibase.configuration.core.DefaultsFileValueProvider; -import liquibase.configuration.core.InteractivePromptingValueProvider; import liquibase.exception.CommandLineParsingException; import liquibase.exception.CommandValidationException; import liquibase.hub.HubConfiguration; @@ -468,7 +467,6 @@ public int getPrecedence() { } else { Scope.getCurrentScope().getLog(getClass()).fine("Cannot find local defaultsFile " + defaultsFile.getAbsolutePath()); } - liquibaseConfiguration.registerProvider(new InteractivePromptingValueProvider()); return returnList; } From 17227e3b771308a769c54eb45897517a657794ea Mon Sep 17 00:00:00 2001 From: Surya Aki Date: Thu, 23 Dec 2021 10:38:07 -0600 Subject: [PATCH 21/22] remvoe InteractivePromptingValueProvider --- .../liquibase/extension/testing/command/CommandTests.groovy | 2 -- 1 file changed, 2 deletions(-) diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index 33cc999604a..b627b259338 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -15,7 +15,6 @@ import liquibase.command.core.InternalSnapshotCommandStep import liquibase.configuration.AbstractMapConfigurationValueProvider import liquibase.configuration.ConfigurationValueProvider import liquibase.configuration.LiquibaseConfiguration -import liquibase.configuration.core.InteractivePromptingValueProvider import liquibase.database.Database import liquibase.database.DatabaseFactory import liquibase.database.jvm.JdbcConnection @@ -88,7 +87,6 @@ class CommandTests extends Specification { } Scope.currentScope.getSingleton(LiquibaseConfiguration).registerProvider(propertiesProvider) - Scope.currentScope.getSingleton(LiquibaseConfiguration).registerProvider(new InteractivePromptingValueProvider()) } def cleanup() { From d7ebf6ec9d0886eb8b1d4822a7dc972b8ae2c0f0 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Mon, 27 Dec 2021 08:20:23 -0600 Subject: [PATCH 22/22] ensure that the most recently created changelog file is prompted for --- .../extension/testing/command/CommandTests.groovy | 7 +++++++ .../testing/setup/SetupCreateTempResources.groovy | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index b627b259338..109bfe4bb57 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -860,6 +860,13 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} this.setups.add(new SetupCreateTempResources(originalFile, newFile, baseDir)) } + /** + * @param fileLastModifiedDate if not null, the newly created file's last modified date will be set to this value + */ + void createTempResource(String originalFile, String newFile, String baseDir, Date fileLastModifiedDate) { + this.setups.add(new SetupCreateTempResources(originalFile, newFile, baseDir, fileLastModifiedDate)) + } + void createTempDirectoryResource(String directory) { this.setups.add(new SetupCreateDirectoryResources(directory)) } diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy index 0de15a1aebd..f864ceaf770 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupCreateTempResources.groovy @@ -8,15 +8,21 @@ class SetupCreateTempResources extends TestSetup { private String originalFile private String newFile private String baseDir + private Date lastModified SetupCreateTempResources(String originalFile, String newFile) { this(originalFile, newFile, "target/test-classes") } SetupCreateTempResources(String originalFile, String newFile, String baseDir) { + this(originalFile, newFile, baseDir, null) + } + + SetupCreateTempResources(String originalFile, String newFile, String baseDir, Date lastModified) { this.originalFile = originalFile this.newFile = newFile this.baseDir = baseDir + this.lastModified = lastModified } @Override @@ -26,5 +32,8 @@ class SetupCreateTempResources extends TestSetup { String contents = FileUtil.getContents(f) File outputFile = new File(baseDir, newFile) FileUtil.write(contents, outputFile) + if (lastModified != null) { + outputFile.setLastModified(lastModified.getTime()) + } } }