-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Provide configuration properties for Flyway's Vault and Conjur support #25456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
c1a7d5f
72044e1
e7490bb
8a5800f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ | |
| * @author Dave Syer | ||
| * @author Eddú Meléndez | ||
| * @author Stephane Nicoll | ||
| * @author Chris Bono | ||
| * @since 1.1.0 | ||
| */ | ||
| @ConfigurationProperties(prefix = "spring.flyway") | ||
|
|
@@ -328,6 +329,33 @@ public class FlywayProperties { | |
| */ | ||
| private Boolean skipExecutingMigrations; | ||
|
|
||
| /** | ||
| * The REST API URL of the Conjur server. Requires Flyway teams. | ||
|
||
| */ | ||
| private String conjurUrl; | ||
|
|
||
| /** | ||
| * The Conjur token required to access secrets. Requires Flyway teams. | ||
| */ | ||
| private String conjurToken; | ||
|
|
||
| /** | ||
| * The REST API URL of the Vault server. Requires Flyway teams. | ||
| */ | ||
| private String vaultUrl; | ||
|
|
||
| /** | ||
| * The Vault token required to access secrets. Requires Flyway teams. | ||
| */ | ||
| private String vaultToken; | ||
|
|
||
| /** | ||
| * A comma-separated list of paths to secrets that contain Flyway configurations. Each | ||
| * path must start with the name of the engine and end with the name of the secret | ||
| * such 'kv/test/1/config'. Requires Flyway teams. | ||
| */ | ||
| private String vaultSecrets; | ||
|
||
|
|
||
| public boolean isEnabled() { | ||
| return this.enabled; | ||
| } | ||
|
|
@@ -772,4 +800,44 @@ public void setSkipExecutingMigrations(Boolean skipExecutingMigrations) { | |
| this.skipExecutingMigrations = skipExecutingMigrations; | ||
| } | ||
|
|
||
| public String getConjurUrl() { | ||
| return conjurUrl; | ||
| } | ||
|
|
||
| public void setConjurUrl(String conjurUrl) { | ||
| this.conjurUrl = conjurUrl; | ||
| } | ||
|
|
||
| public String getConjurToken() { | ||
| return conjurToken; | ||
| } | ||
|
|
||
| public void setConjurToken(String conjurToken) { | ||
| this.conjurToken = conjurToken; | ||
| } | ||
|
|
||
| public String getVaultUrl() { | ||
| return vaultUrl; | ||
| } | ||
|
|
||
| public void setVaultUrl(String vaultUrl) { | ||
| this.vaultUrl = vaultUrl; | ||
| } | ||
|
|
||
| public String getVaultToken() { | ||
| return vaultToken; | ||
| } | ||
|
|
||
| public void setVaultToken(String vaultToken) { | ||
| this.vaultToken = vaultToken; | ||
| } | ||
|
|
||
| public String getVaultSecrets() { | ||
| return vaultSecrets; | ||
| } | ||
|
|
||
| public void setVaultSecrets(String vaultSecrets) { | ||
| this.vaultSecrets = vaultSecrets; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,6 +82,7 @@ | |
| * @author Dominic Gunn | ||
| * @author András Deák | ||
| * @author Takaaki Shimbo | ||
| * @author Chris Bono | ||
| */ | ||
| @ExtendWith(OutputCaptureExtension.class) | ||
| class FlywayAutoConfigurationTests { | ||
|
|
@@ -412,35 +413,19 @@ void configurationCustomizersAreConfiguredAndOrdered() { | |
|
|
||
| @Test | ||
| void batchIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.batch=true").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" batch "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.batch=true", "batch"); | ||
| } | ||
|
|
||
| @Test | ||
| void dryRunOutputIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.dryRunOutput=dryrun.sql").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" dryRunOutput "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.dryRunOutput=dryrun.sql", | ||
| "dryRunOutput"); | ||
| } | ||
|
|
||
| @Test | ||
| void errorOverridesIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.errorOverrides=D12345").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" errorOverrides "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.errorOverrides=D12345", | ||
| "errorOverrides"); | ||
| } | ||
|
|
||
| @Test | ||
|
|
@@ -452,46 +437,25 @@ void licenseKeyIsCorrectlyMapped(CapturedOutput output) { | |
|
|
||
| @Test | ||
| void oracleSqlplusIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.oracle-sqlplus=true").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" oracle.sqlplus "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.oracle-sqlplus=true", | ||
| "oracle.sqlplus"); | ||
| } | ||
|
|
||
| @Test | ||
| void oracleSqlplusWarnIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.oracle-sqlplus-warn=true").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" oracle.sqlplusWarn "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.oracle-sqlplus-warn=true", | ||
| "oracle.sqlplusWarn"); | ||
| } | ||
|
|
||
| @Test | ||
| void streamIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.stream=true").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" stream "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.stream=true", "stream"); | ||
| } | ||
|
|
||
| @Test | ||
| void undoSqlMigrationPrefix() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.undo-sql-migration-prefix=undo").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" undoSqlMigrationPrefix "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.undo-sql-migration-prefix=undo", | ||
| "undoSqlMigrationPrefix"); | ||
| } | ||
|
|
||
| @Test | ||
|
|
@@ -525,67 +489,77 @@ void initSqlsWithFlywayUrl() { | |
|
|
||
| @Test | ||
| void cherryPickIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.cherry-pick=1.1").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" cherryPick "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.cherry-pick=1.1", "cherryPick"); | ||
| } | ||
|
|
||
| @Test | ||
| void jdbcPropertiesAreCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.jdbc-properties.prop=value").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" jdbcProperties "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.jdbc-properties.prop=value", | ||
| "jdbcProperties"); | ||
| } | ||
|
|
||
| @Test | ||
| void oracleKerberosCacheFileIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.oracle-kerberos-cache-file=/tmp/cache").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" oracle.kerberosCacheFile "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException( | ||
| "spring.flyway.oracle-kerberos-cache-file=/tmp/cache", "oracle.kerberosCacheFile"); | ||
| } | ||
|
|
||
| @Test | ||
| void oracleKerberosConfigFileIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.oracle-kerberos-config-file=/tmp/config").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" oracle.kerberosConfigFile "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException( | ||
| "spring.flyway.oracle-kerberos-config-file=/tmp/config", "oracle.kerberosConfigFile"); | ||
| } | ||
|
|
||
| @Test | ||
| void outputQueryResultsIsCorrectlyMapped() { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
| .withPropertyValues("spring.flyway.output-query-results=false").run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" outputQueryResults "); | ||
| }); | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.output-query-results=false", | ||
| "outputQueryResults"); | ||
| } | ||
|
|
||
| @Test | ||
| void skipExecutingMigrationsIsCorrectlyMapped() { | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.skip-executing-migrations=true", | ||
| "skipExecutingMigrations"); | ||
| } | ||
|
|
||
| @Test | ||
| void conjurUrlIsCorrectlyMapped() { | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException( | ||
| "spring.flyway.conjur-url=http://foo.com/secrets", "conjurUrl"); | ||
| } | ||
|
|
||
| @Test | ||
| void conjurTokenIsCorrectlyMapped() { | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.conjur-token=5150", | ||
| "conjurToken"); | ||
| } | ||
|
|
||
| @Test | ||
| void vaultUrlIsCorrectlyMapped() { | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.vault-url=http://foo.com/secrets", | ||
| "vaultUrl"); | ||
| } | ||
|
|
||
| @Test | ||
| void vaultTokenIsCorrectlyMapped() { | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.vault-token=5150", "vaultToken"); | ||
| } | ||
|
|
||
| @Test | ||
| void vaultSecretsIsCorrectlyMapped() { | ||
| assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException("spring.flyway.vault-secrets=kv/test/1/config", | ||
| "vaultSecrets"); | ||
| } | ||
|
|
||
| @Test | ||
|
||
| private void assertThatPropertyResultsInFlywayTeamsUpgradeRequiredException(String propertyKeyAndValue, | ||
|
||
| String flywayPropertyNameInException) { | ||
| this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @snicoll thx for the suggestion. Keeping the setup in each test makes it easy to see what the test is doing from first glance. Sharing only the common validation reduces the duplicated lines (and that was the main goal of the first attempt). 👍🏻 |
||
| .withPropertyValues("spring.flyway.skip-executing-migrations=true").run((context) -> { | ||
| .withPropertyValues(propertyKeyAndValue).run((context) -> { | ||
| assertThat(context).hasFailed(); | ||
| Throwable failure = context.getStartupFailure(); | ||
| assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class); | ||
| assertThat(failure).hasMessageContaining(" skipExecutingMigrations "); | ||
| assertThat(failure).hasMessageContaining(String.format(" %s ", flywayPropertyNameInException)); | ||
| }); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ | |
| * Tests for {@link FlywayProperties}. | ||
| * | ||
| * @author Stephane Nicoll | ||
| * @author Chris Bono | ||
| */ | ||
| class FlywayPropertiesTests { | ||
|
|
||
|
|
@@ -108,9 +109,7 @@ void expectedPropertiesAreManaged() { | |
| // Handled by the conversion service | ||
| ignoreProperties(configuration, "baselineVersionAsString", "encodingAsString", "locationsAsStrings", | ||
| "targetAsString"); | ||
| // Teams-only properties that we cannot detect as no exception is thrown and | ||
| // getters return null | ||
|
||
| ignoreProperties(configuration, "conjurToken", "conjurUrl", "vaultSecrets", "vaultToken", "vaultUrl"); | ||
| // Handled as initSql array | ||
| ignoreProperties(configuration, "initSql"); | ||
| ignoreProperties(properties, "initSqls"); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.