Skip to content

Commit

Permalink
Merge branch 'main' of github.com:liquibase/liquibase-mongodb into fe…
Browse files Browse the repository at this point in the history
…rretdb
  • Loading branch information
robertericreeves committed Apr 14, 2023
2 parents 43c0c10 + a6350f1 commit 4a0b8f0
Show file tree
Hide file tree
Showing 41 changed files with 531 additions and 99 deletions.
25 changes: 24 additions & 1 deletion .github/workflows/release-published.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,27 @@ jobs:
env:
MAVEN_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.SONATYPE_TOKEN }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}

deploy_xsd:
name: Upload xsds
runs-on: ubuntu-20.04
outputs:
tag: ${{ steps.collect-data.outputs.tag }}
version: ${{ needs.setup.outputs.version }}
steps:
- name: Download liquibase mongodb xsd
uses: actions/checkout@v3
with:
# Relative path under $GITHUB_WORKSPACE to place the repository
path: liquibase-mongodb
repository: "liquibase/liquibase-mongodb"

- name: Upload to s3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.LIQUIBASEORIGIN_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.LIQUIBASEORIGIN_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: us-east-1
# aws s3 sync syncs directories and S3 prefixes.
run: |
aws s3 sync liquibase-mongodb/src/main/resources/www.liquibase.org/xml/ns/mongodb/ s3://liquibaseorg-origin/xml/ns/mongodb/ --content-type application/octet-stream --only-show-errors
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Liquibase turned to be the most feasible tool to extend as it allows to define c
<a name="release-notes"></a>
## Release Notes

#### 4.21.0
* Support for Liquibase 4.20.0

#### 4.4.0
* Updated code to work with core 4.4.0 [PR #147](https://github.com/liquibase/liquibase-mongodb/pull/147)
* Bump mockito-core from 3.10.0 to 3.11.0 [PR#151](https://github.com/liquibase/liquibase-mongodb/pull/151)
Expand Down
27 changes: 27 additions & 0 deletions README.test-harness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Using the Liquibase Test Harness in the MongoDB Extension
The liquibase-mongodb extension now comes with integration test support via the liquibase-test-harness.
This Liquibase test framework is designed to *also* make it easier for you to test your extensions.

### Configuring your project

#### Configuring your connections

- Use the provided `harness-config.yml` file in `src/test/resources` directory.
- Update this file to add the connection information for all the databases you want the Liquibase MongoDB extension to be tested against.
- *If this config file does not exist, create a new one using this as an example : https://github.com/liquibase/liquibase-test-harness/blob/main/src/test/resources/harness-config.yml*
- Your database under test needs to be completely empty prior to the Harness tests running.

#### Executing the Harness NoSQL Foundational test
- From your IDE, right-click on the `HarnessNoSqlCompatibility` test class present in `src/test/groovy/liquibase/harness/compatibility/foundational` directory.
- Doing so, will allow you to execute NoSQL Foundational harness suite. Test data for this test should be located in the next directories:
- `src/test/resources/liquibase/harness/compatibility/foundational/changelogs/nosql` for the changelogs you want to test. XML, JSON & YAML formats are supported.
- `src/test/resources/liquibase/harness/compatibility/foundational/expectedResultSet/mongodb` for the JSON format files with the values you expect to be present in the DATABASECHANGELOG table after applying your changelog files.
In the key:value format like: `"id":"1"`, `"author":"as"`,`"description":"createCollection collectionName=towns"`, etc. Use existing files as an example.

##### Alternative ways to run the Harness test suites
- Using maven by executing next command:
`mvn -Dtest="HarnessNoSqlCompatibility" -DdbName=mongodb(optional) -DdbUsername=USERNAME(optional) -DdbPassword=PASSWORD(optional) -DdbUrl=URL(optional) test`
- where USERNAME, PASSWORD and URL are connection credentials.

#### Troubleshooting notes
- If your IDE doesn't allow you to run HarnessNoSqlCompatibility as a test class, mark test/groovy folder as test classes folder in your IDE
26 changes: 16 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-mongodb</artifactId>
<packaging>jar</packaging>
<version>4.19.1-SNAPSHOT</version>
<version>4.21.1-SNAPSHOT</version>
<name>Liquibase MongoDB Extension</name>
<description>Liquibase Extension for MongoDB</description>
<url>http://www.liquibase.org</url>
Expand Down Expand Up @@ -42,7 +42,7 @@
<jupiter.surefire.version>1.3.2</jupiter.surefire.version>
<mockito-core.version>4.11.0</mockito-core.version>
<mockito-junit-jupiter.version>4.8.0</mockito-junit-jupiter.version>
<mongodb-driver.version>4.8.2</mongodb-driver.version>
<mongodb-driver.version>4.9.1</mongodb-driver.version>
<lombok.version>1.18.26</lombok.version>
<hamcrest.version>1.3</hamcrest.version>
<assertj.version>3.24.2</assertj.version>
Expand All @@ -54,7 +54,7 @@
<license-maven-plugin.version>2.0.0</license-maven-plugin.version>
<maven-help-plugin.version>3.2.0</maven-help-plugin.version>
<jackson-core.version>2.14.2</jackson-core.version>
<snakeyaml.version>1.33</snakeyaml.version>
<snakeyaml.version>2.0</snakeyaml.version>
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
Expand All @@ -65,13 +65,19 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.19.0</version>
<version>4.20.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>3.0.14</version>
<version>3.0.17</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-testng</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
Expand All @@ -94,7 +100,7 @@
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220924</version>
<version>20230227</version>
</dependency>
<dependency>
<groupId>org.skyscreamer</groupId>
Expand Down Expand Up @@ -192,13 +198,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.6</version>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.6</version>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down Expand Up @@ -241,7 +247,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<version>3.0.0</version>
<configuration>
<!-- <skipTests>false</skipTests>-->
<redirectTestOutputToFile>true</redirectTestOutputToFile>
Expand Down Expand Up @@ -278,7 +284,7 @@
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit-platform</artifactId>
<version>2.22.2</version>
<version>3.0.0</version>
</dependency>
</dependencies>
</plugin>
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/liquibase/ext/mongodb/database/MongoConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Driver;
import java.util.Collections;
import java.util.Objects;
Expand Down Expand Up @@ -121,8 +123,8 @@ private String injectCredentials(final String url, final Properties driverProper

if (nonNull(driverProperties)) {

final Optional<String> user = Optional.ofNullable(StringUtil.trimToNull(driverProperties.getProperty("user")));
final Optional<String> password = Optional.ofNullable(StringUtil.trimToNull(driverProperties.getProperty("password")));
final Optional<String> user = Optional.ofNullable(StringUtil.trimToNull(driverProperties.getProperty("user"))).map(MongoConnection::encode);
final Optional<String> password = Optional.ofNullable(StringUtil.trimToNull(driverProperties.getProperty("password"))).map(MongoConnection::encode);

if (user.isPresent()) {
// injects credentials
Expand All @@ -136,6 +138,13 @@ private String injectCredentials(final String url, final Properties driverProper
return url;
}

private static String encode(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}

@Override
public void close() throws DatabaseException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,16 @@ protected List<DatabaseChangeLogLock> queryLocks() throws DatabaseException {

@Override
protected Boolean existsRepository() throws DatabaseException {
return getExecutor().queryForLong(new CountCollectionByNameStatement(getDatabase().getDatabaseChangeLogLockTableName())) == 1L;
try {
return getExecutor().queryForLong(new CountCollectionByNameStatement(getDatabase().getDatabaseChangeLogLockTableName())) == 1L;
} catch (DatabaseException e){
if("Could not query for long".equalsIgnoreCase(e.getMessage())){
//"Could not query for long" is not meaningful let's remove it from trace and rethrow underlying exception
throw new DatabaseException("Failed to create or initialize the lock table",e.getCause());
} else {
throw e;
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
import liquibase.exception.DatabaseException;
import liquibase.exception.DatabaseHistoryException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.executor.Executor;
import liquibase.executor.ExecutorService;
import liquibase.executor.LoggingExecutor;
import liquibase.logging.Logger;
import liquibase.nosql.database.AbstractNoSqlDatabase;
import liquibase.nosql.executor.NoSqlExecutor;
Expand All @@ -37,6 +39,7 @@
import java.time.Clock;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;

import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
Expand All @@ -51,6 +54,8 @@ public abstract class AbstractNoSqlHistoryService<D extends AbstractNoSqlDatabas

private boolean serviceInitialized;

private static final ResourceBundle mongoBundle = ResourceBundle.getBundle("liquibase/i18n/liquibase-mongo");

@Getter
private Boolean hasDatabaseChangeLogTable;

Expand Down Expand Up @@ -88,8 +93,12 @@ public D getNoSqlDatabase() {
return (D) getDatabase();
}

public NoSqlExecutor getExecutor() {
return (NoSqlExecutor) Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(NoSqlExecutor.EXECUTOR_NAME, getDatabase());
public NoSqlExecutor getExecutor() throws DatabaseException {
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(NoSqlExecutor.EXECUTOR_NAME, getDatabase());
if (executor instanceof LoggingExecutor) {
throw new DatabaseException(String.format(mongoBundle.getString("command.unsupported"), "*sql"));
}
return (NoSqlExecutor) executor ;
}

@Override
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/liquibase/nosql/executor/NoSqlExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,13 @@ public void execute(final SqlStatement sql, final List<SqlVisitor> sqlVisitors)
} else if (sql instanceof UpdateStatement) {
execute((UpdateStatement) sql);
} else {
throw new IllegalArgumentException("Mongodb cannot execute "+sql.getClass().getName()+" statements");
throw new DatabaseException("liquibase-mongodb extension cannot execute changeset \n" +
"Unknown type: " + sql.getClass().getName() +
"\nPlease check the following common causes:\n" +
"- Verify change set definitions for common error such as: changeType name, changeSet attributes spelling " +
"(such as runWith, context, etc.), and punctuation.\n" +
"- Verify that changesets have all the required changeset attributes and do not have invalid attributes for the designated change type.\n" +
"- Double-check to make sure your basic setup includes all needed extensions in your Java classpath");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
import liquibase.exception.DatabaseException;
import liquibase.exception.LockException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.executor.Executor;
import liquibase.executor.ExecutorService;
import liquibase.executor.LoggingExecutor;
import liquibase.lockservice.DatabaseChangeLogLock;
import liquibase.lockservice.LockService;
import liquibase.logging.Logger;
Expand All @@ -39,6 +41,7 @@
import java.text.DateFormat;
import java.time.Clock;
import java.util.List;
import java.util.ResourceBundle;

import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
Expand All @@ -51,6 +54,8 @@ public abstract class AbstractNoSqlLockService<D extends AbstractNoSqlDatabase>

private boolean hasChangeLogLock;

private static final ResourceBundle mongoBundle = ResourceBundle.getBundle("liquibase/i18n/liquibase-mongo");

private Long changeLogLockPollRate;

private Long changeLogLockRecheckTime;
Expand Down Expand Up @@ -83,8 +88,12 @@ public D getDatabase() {
return database;
}

public NoSqlExecutor getExecutor() {
return (NoSqlExecutor) Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(NoSqlExecutor.EXECUTOR_NAME, getDatabase());
public NoSqlExecutor getExecutor() throws DatabaseException {
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(NoSqlExecutor.EXECUTOR_NAME, getDatabase());
if (executor instanceof LoggingExecutor) {
throw new DatabaseException(String.format(mongoBundle.getString("command.unsupported"), "*sql"));
}
return (NoSqlExecutor) executor ;
}

@Override
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/liquibase/nosql/snapshot/NoSqlSnapshotGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package liquibase.nosql.snapshot;

import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.ext.mongodb.database.MongoLiquibaseDatabase;
import liquibase.snapshot.DatabaseSnapshot;
import liquibase.snapshot.InvalidExampleException;
import liquibase.snapshot.SnapshotGenerator;
import liquibase.snapshot.SnapshotGeneratorChain;
import liquibase.structure.DatabaseObject;

import java.util.ResourceBundle;

import static liquibase.plugin.Plugin.PRIORITY_SPECIALIZED;

public class NoSqlSnapshotGenerator implements SnapshotGenerator {
private static final ResourceBundle mongoBundle = ResourceBundle.getBundle("liquibase/i18n/liquibase-mongo");

@Override
public int getPriority(Class<? extends DatabaseObject> objectType, Database database) {
if (database instanceof MongoLiquibaseDatabase) {
return PRIORITY_SPECIALIZED;
}
return PRIORITY_NONE;
}

@Override
public <T extends DatabaseObject> T snapshot(T example, DatabaseSnapshot snapshot, SnapshotGeneratorChain chain) throws DatabaseException, InvalidExampleException {
throw new DatabaseException(String.format(mongoBundle.getString("command.unsupported"), "db-doc, diff*, generate-changelog, and snapshot*"));
}

@Override
public Class<? extends DatabaseObject>[] addsTo() {
return new Class[0];
}

@Override
public Class<? extends SnapshotGenerator>[] replaces() {
return new Class[0];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
liquibase.nosql.snapshot.NoSqlSnapshotGenerator
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
command.unsupported=Liquibase MongoDB Extension does not support %s commands\nPlease refer to our documentation for the entire list of supported commands for MongoDB
Loading

0 comments on commit 4a0b8f0

Please sign in to comment.