diff --git a/README.md b/README.md
index ad96ee9..d1311c1 100644
--- a/README.md
+++ b/README.md
@@ -50,19 +50,22 @@ All subsequent changes are applied to the created DB.
* createContainer [REST](https://docs.microsoft.com/en-us/rest/api/cosmos-db/create-a-collection) [SDK](https://docs.microsoft.com/en-us/java/api/com.azure.cosmos.cosmosdatabase.createcontainer?view=azure-java-stable)
-Creates a Cosmos container while passing additional request options.
+Creates a Cosmos container while passing additional request properties.
+There is a possibility to pass throughput properties either manual as a number or auto as a json.
There is a flag to skip if exists and do not fail.
-If no options are specified then a ``/null`` partition key path is the default one.
+If no properties are specified then a ``/null`` partition key path is the default one.
* replaceContainer [REST](https://docs.microsoft.com/en-us/rest/api/cosmos-db/replace-a-collection) [SDK](https://docs.microsoft.com/en-us/java/api/com.azure.cosmos.cosmoscontainer.replace?view=azure-java-stable)
-Replaces the container properties by container name.
+Replaces the container properties by container id.
+There is a possibility to pass throughput properties either manual as a number or auto as a json.
+If only properties specified no throughput properties will be amended and viceversa.
* deleteContainer [REST](https://docs.microsoft.com/en-us/rest/api/cosmos-db/delete-a-collection) [SDK](https://docs.microsoft.com/en-us/java/api/com.azure.cosmos.cosmoscontainer.delete?view=azure-java-stable)
-Deletes the Cosmos container by name.
+Deletes the Cosmos container by id.
There is a flag to skip if missing and do not fail.
diff --git a/src/main/java/liquibase/ext/cosmosdb/change/CreateContainerChange.java b/src/main/java/liquibase/ext/cosmosdb/change/CreateContainerChange.java
index 16c9ff7..2b79f84 100644
--- a/src/main/java/liquibase/ext/cosmosdb/change/CreateContainerChange.java
+++ b/src/main/java/liquibase/ext/cosmosdb/change/CreateContainerChange.java
@@ -23,16 +23,12 @@
import liquibase.change.ChangeMetaData;
import liquibase.change.DatabaseChange;
import liquibase.database.Database;
-import liquibase.ext.cosmosdb.statement.CreateContainerIfNotExistsStatement;
import liquibase.ext.cosmosdb.statement.CreateContainerStatement;
import liquibase.statement.SqlStatement;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
-import static java.lang.Boolean.FALSE;
-import static java.util.Optional.ofNullable;
-
@DatabaseChange(name = "createContainer",
description = "Create container " +
"https://docs.microsoft.com/en-us/java/api/com.azure.cosmos.cosmosdatabase.createcontainer?view=azure-java-stable\n" +
@@ -45,6 +41,7 @@ public class CreateContainerChange extends AbstractCosmosChange {
private String containerName;
private String options;
+ private String throughput;
private Boolean skipExisting;
@Override
@@ -56,7 +53,7 @@ public String getConfirmationMessage() {
public SqlStatement[] generateStatements(final Database database) {
final CreateContainerStatement createContainerStatement =
- ofNullable(skipExisting).orElse(FALSE) ? new CreateContainerIfNotExistsStatement(containerName, options) : new CreateContainerStatement(containerName, options);
+ new CreateContainerStatement(containerName, options, throughput, skipExisting);
return new SqlStatement[]{
createContainerStatement
diff --git a/src/main/java/liquibase/ext/cosmosdb/change/ReplaceContainerChange.java b/src/main/java/liquibase/ext/cosmosdb/change/ReplaceContainerChange.java
index 0ae7dcf..c4a82c7 100644
--- a/src/main/java/liquibase/ext/cosmosdb/change/ReplaceContainerChange.java
+++ b/src/main/java/liquibase/ext/cosmosdb/change/ReplaceContainerChange.java
@@ -24,6 +24,7 @@
import liquibase.change.DatabaseChange;
import liquibase.database.Database;
import liquibase.ext.cosmosdb.statement.CreateContainerStatement;
+import liquibase.ext.cosmosdb.statement.ReplaceContainerStatement;
import liquibase.statement.SqlStatement;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -42,6 +43,7 @@ public class ReplaceContainerChange extends AbstractCosmosChange {
private String containerName;
private String options;
+ private String throughput;
@Override
public String getConfirmationMessage() {
@@ -52,7 +54,7 @@ public String getConfirmationMessage() {
public SqlStatement[] generateStatements(final Database database) {
final CreateContainerStatement createContainerStatement
- = new CreateContainerStatement(containerName, options);
+ = new ReplaceContainerStatement(containerName, options, throughput);
return new SqlStatement[]{
createContainerStatement
diff --git a/src/main/java/liquibase/ext/cosmosdb/statement/AbstractNoSqlStatement.java b/src/main/java/liquibase/ext/cosmosdb/statement/AbstractNoSqlStatement.java
index a2fc14c..feb5245 100644
--- a/src/main/java/liquibase/ext/cosmosdb/statement/AbstractNoSqlStatement.java
+++ b/src/main/java/liquibase/ext/cosmosdb/statement/AbstractNoSqlStatement.java
@@ -38,4 +38,9 @@ public boolean skipOnUnsupported() {
public abstract String toJs();
+ @Override
+ public String toString() {
+ return toJs();
+ }
+
}
diff --git a/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerIfNotExistsStatement.java b/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerIfNotExistsStatement.java
deleted file mode 100644
index d736370..0000000
--- a/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerIfNotExistsStatement.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package liquibase.ext.cosmosdb.statement;
-
-/*-
- * #%L
- * Liquibase CosmosDB Extension
- * %%
- * Copyright (C) 2020 Mastercard
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * #L%
- */
-
-import com.azure.cosmos.CosmosDatabase;
-import com.azure.cosmos.models.CosmosContainerProperties;
-import lombok.AllArgsConstructor;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-
-@AllArgsConstructor
-@Getter
-@EqualsAndHashCode(callSuper = true)
-public class CreateContainerIfNotExistsStatement extends CreateContainerStatement {
-
- public static final String COMMAND_NAME = "createContainerIfNotExists";
-
- public CreateContainerIfNotExistsStatement(final String containerName, final String options) {
- super(containerName, options);
- }
-
- @Override
- public String getCommandName() {
- return COMMAND_NAME;
- }
-
- @Override
- public void execute(final CosmosDatabase cosmosDatabase) {
- final CosmosContainerProperties cosmosContainerProperties = JsonUtils.toContainerProperties(containerName, options);
- cosmosDatabase.createContainerIfNotExists(cosmosContainerProperties);
- }
-
- @Override
- public String toString() {
- return toJs();
- }
-}
diff --git a/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerStatement.java b/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerStatement.java
index aff3148..9646813 100644
--- a/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerStatement.java
+++ b/src/main/java/liquibase/ext/cosmosdb/statement/CreateContainerStatement.java
@@ -22,11 +22,17 @@
import com.azure.cosmos.CosmosDatabase;
import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.ThroughputProperties;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
+import static java.lang.Boolean.FALSE;
+import static java.util.Optional.ofNullable;
+import static liquibase.ext.cosmosdb.statement.JsonUtils.toContainerProperties;
+import static liquibase.ext.cosmosdb.statement.JsonUtils.toThroughputProperties;
+
@AllArgsConstructor
@NoArgsConstructor
@Getter
@@ -35,8 +41,18 @@ public class CreateContainerStatement extends AbstractNoSqlStatement implements
public static final String COMMAND_NAME = "createContainer";
- protected String containerName;
- protected String options;
+ private String containerName;
+ private String options;
+ private String throughput;
+ private Boolean skipExisting;
+
+ public CreateContainerStatement(final String containerName, final String options, final String throughput) {
+ this(containerName, options, throughput, FALSE);
+ }
+
+ public CreateContainerStatement(final String containerName, final String options) {
+ this(containerName, options, null);
+ }
public CreateContainerStatement(final String containerName) {
this(containerName, null);
@@ -53,22 +69,25 @@ public String toJs() {
"db."
+ getCommandName()
+ "("
- + containerName
+ + getContainerName()
+ + ", "
+ + getOptions()
+ ", "
- + options
+ + getThroughput()
+ + ", "
+ + getSkipExisting()
+ ");";
}
@Override
public void execute(final CosmosDatabase cosmosDatabase) {
-
- final CosmosContainerProperties cosmosContainerProperties = JsonUtils.toContainerProperties(containerName, options);
- cosmosDatabase.createContainer(cosmosContainerProperties);
+ final CosmosContainerProperties cosmosContainerProperties = toContainerProperties(getContainerName(), getOptions());
+ final ThroughputProperties throughputProperties = toThroughputProperties(getThroughput());
+ if (ofNullable(skipExisting).orElse(FALSE)) {
+ cosmosDatabase.createContainerIfNotExists(cosmosContainerProperties, throughputProperties);
+ } else {
+ cosmosDatabase.createContainer(cosmosContainerProperties, throughputProperties);
+ }
}
-
- @Override
- public String toString() {
- return toJs();
- }
}
diff --git a/src/main/java/liquibase/ext/cosmosdb/statement/JsonUtils.java b/src/main/java/liquibase/ext/cosmosdb/statement/JsonUtils.java
index 3115117..3f4effb 100644
--- a/src/main/java/liquibase/ext/cosmosdb/statement/JsonUtils.java
+++ b/src/main/java/liquibase/ext/cosmosdb/statement/JsonUtils.java
@@ -24,15 +24,20 @@
import com.azure.cosmos.implementation.JsonSerializable;
import com.azure.cosmos.implementation.Utils;
import com.azure.cosmos.models.*;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import liquibase.util.StringUtil;
+import com.fasterxml.jackson.databind.node.ContainerNode;
+import com.fasterxml.jackson.databind.node.ValueNode;
import lombok.NoArgsConstructor;
import com.azure.cosmos.implementation.Document;
import java.util.Map;
+import static com.azure.cosmos.implementation.Constants.Properties.AUTOPILOT_MAX_THROUGHPUT;
import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable;
+import static liquibase.util.StringUtil.isNotEmpty;
import static liquibase.util.StringUtil.trimToNull;
import static lombok.AccessLevel.PRIVATE;
@@ -97,7 +102,7 @@ public static Document mergeDocuments(final Document destination, final Document
public static CosmosContainerProperties toContainerProperties(final String containerName, final String optionsJson) {
final CosmosContainerProperties cosmosContainerProperties = new CosmosContainerProperties(containerName, DEFAULT_PARTITION_KEY_PATH);
- if (StringUtil.isNotEmpty(StringUtil.trimToNull(optionsJson))) {
+ if (isNotEmpty(trimToNull(optionsJson))) {
final DocumentCollection documentCollection = new DocumentCollection(optionsJson);
if(nonNull(documentCollection.getPartitionKey())) {
cosmosContainerProperties.setPartitionKeyDefinition(documentCollection.getPartitionKey());
@@ -120,4 +125,23 @@ public static CosmosContainerProperties toContainerProperties(final String conta
}
return cosmosContainerProperties;
}
+
+ public static ThroughputProperties toThroughputProperties(final String throughput) {
+
+ if (nonNull(trimToNull(throughput))) {
+ final TreeNode node;
+ try {
+ node = OBJECT_MAPPER.readTree(throughput);
+ } catch (final JsonProcessingException e) {
+ throw new IllegalArgumentException(String.format("Unable to parse JSON %s", throughput), e);
+ }
+ if(node.isValueNode()) {
+ return ThroughputProperties.createManualThroughput(((ValueNode)node).asInt());
+ }
+ if(node.isContainerNode() && ((ContainerNode>)node).has(AUTOPILOT_MAX_THROUGHPUT)) {
+ return ThroughputProperties.createAutoscaledThroughput(((ValueNode)node.get(AUTOPILOT_MAX_THROUGHPUT)).asInt());
+ }
+ }
+ return null;
+ }
}
diff --git a/src/main/java/liquibase/ext/cosmosdb/statement/ReplaceContainerStatement.java b/src/main/java/liquibase/ext/cosmosdb/statement/ReplaceContainerStatement.java
index a600abb..4ad77da 100644
--- a/src/main/java/liquibase/ext/cosmosdb/statement/ReplaceContainerStatement.java
+++ b/src/main/java/liquibase/ext/cosmosdb/statement/ReplaceContainerStatement.java
@@ -22,10 +22,16 @@
import com.azure.cosmos.CosmosDatabase;
import com.azure.cosmos.models.CosmosContainerProperties;
+import com.azure.cosmos.models.ThroughputProperties;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
+import static java.util.Objects.nonNull;
+import static liquibase.ext.cosmosdb.statement.JsonUtils.toContainerProperties;
+import static liquibase.ext.cosmosdb.statement.JsonUtils.toThroughputProperties;
+import static liquibase.util.StringUtil.trimToNull;
+
@AllArgsConstructor
@Getter
@EqualsAndHashCode(callSuper = true)
@@ -33,8 +39,8 @@ public class ReplaceContainerStatement extends CreateContainerStatement {
public static final String COMMAND_NAME = "replaceContainer";
- public ReplaceContainerStatement(final String containerName, final String options) {
- super(containerName, options);
+ public ReplaceContainerStatement(final String containerName, final String options, String throughput) {
+ super(containerName, options, throughput);
}
@Override
@@ -44,8 +50,14 @@ public String getCommandName() {
@Override
public void execute(final CosmosDatabase cosmosDatabase) {
- final CosmosContainerProperties cosmosContainerProperties = JsonUtils.toContainerProperties(containerName, options);
- cosmosDatabase.getContainer(containerName).replace(cosmosContainerProperties);
+ if(nonNull(trimToNull(getOptions()))) {
+ final CosmosContainerProperties cosmosContainerProperties = toContainerProperties(getContainerName(), getOptions());
+ cosmosDatabase.getContainer(getContainerName()).replace(cosmosContainerProperties);
+ }
+ if(nonNull(trimToNull(getThroughput()))) {
+ final ThroughputProperties throughputProperties = toThroughputProperties(getThroughput());
+ cosmosDatabase.getContainer(getContainerName()).replaceThroughput(throughputProperties);
+ }
}
@Override
diff --git a/src/main/resources/liquibase.parser.core.xml/dbchangelog-ext.xsd b/src/main/resources/liquibase.parser.core.xml/dbchangelog-ext.xsd
index 1e6dab6..47953c7 100644
--- a/src/main/resources/liquibase.parser.core.xml/dbchangelog-ext.xsd
+++ b/src/main/resources/liquibase.parser.core.xml/dbchangelog-ext.xsd
@@ -9,9 +9,10 @@
-
+
-
+
+
@@ -24,9 +25,10 @@
-
-
-
+
+
+
+
diff --git a/src/test/java/liquibase/ext/cosmosdb/CosmosLiquibaseIT.java b/src/test/java/liquibase/ext/cosmosdb/CosmosLiquibaseIT.java
index 82bfd01..14c5625 100644
--- a/src/test/java/liquibase/ext/cosmosdb/CosmosLiquibaseIT.java
+++ b/src/test/java/liquibase/ext/cosmosdb/CosmosLiquibaseIT.java
@@ -23,6 +23,8 @@
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.models.CosmosContainerProperties;
import com.azure.cosmos.models.CosmosStoredProcedureProperties;
+import com.azure.cosmos.models.IndexingMode;
+import com.azure.cosmos.models.ThroughputProperties;
import liquibase.Liquibase;
import liquibase.ext.cosmosdb.changelog.CosmosRanChangeSet;
import liquibase.resource.ClassLoaderResourceAccessor;
@@ -77,7 +79,33 @@ void testUpdateCreateContainer() {
final CosmosContainerProperties maximal = containerProperties.stream().filter(c -> c.getId().equals("maximal")).findFirst().orElse(null);
assertThat(maximal).isNotNull();
- assertThat(containerProperties).hasSize(5);
+ assertThat(containerProperties).hasSize(7);
+ }
+
+ @SneakyThrows
+ @Test
+ void testUpdateReplaceContainer() {
+ final Liquibase liquibase = new Liquibase("liquibase/ext/changelog.replace-container.test.xml", new ClassLoaderResourceAccessor(), cosmosLiquibaseDatabase);
+ liquibase.update("");
+ assertThat(cosmosDatabase.getContainer(cosmosLiquibaseDatabase.getDatabaseChangeLogLockTableName()).read()).isNotNull();
+ assertThat(cosmosDatabase.getContainer(cosmosLiquibaseDatabase.getDatabaseChangeLogTableName()).read()).isNotNull();
+
+ assertThat(cosmosDatabase.getContainer("minimal").read()).isNotNull();
+ assertThat(cosmosDatabase.getContainer("minimal").read().getProperties()).isNotNull();
+ assertThat(cosmosDatabase.getContainer("minimal").readThroughput()).isNotNull();
+
+ final CosmosContainerProperties maximalProperties = cosmosDatabase.getContainer("maximal").read().getProperties();
+ assertThat(maximalProperties).isNotNull();
+ assertThat(maximalProperties.getId()).isEqualTo("maximal");
+ //TODO: Review after fixed replace
+ assertThat(maximalProperties.getIndexingPolicy().getIndexingMode()).isEqualTo(IndexingMode.CONSISTENT);
+ assertThat(maximalProperties.getIndexingPolicy().isAutomatic()).isTrue();
+ assertThat(maximalProperties.getIndexingPolicy().getIncludedPaths()).hasSize(1);
+ assertThat(maximalProperties.getIndexingPolicy().getExcludedPaths()).hasSize(1);
+
+ final ThroughputProperties maximalThroughput = cosmosDatabase.getContainer("maximal").readThroughput().getProperties();
+ assertThat(maximalThroughput).isNotNull();
+ assertThat(maximalThroughput.getAutoscaleMaxThroughput()).isEqualTo(8000);
}
@SneakyThrows
diff --git a/src/test/java/liquibase/ext/cosmosdb/change/CreateContainerChangeTest.java b/src/test/java/liquibase/ext/cosmosdb/change/CreateContainerChangeTest.java
index 1762526..35472cb 100644
--- a/src/test/java/liquibase/ext/cosmosdb/change/CreateContainerChangeTest.java
+++ b/src/test/java/liquibase/ext/cosmosdb/change/CreateContainerChangeTest.java
@@ -20,62 +20,78 @@
* #L%
*/
+import liquibase.change.Change;
+import liquibase.change.CheckSum;
+import liquibase.changelog.ChangeSet;
+import liquibase.database.core.PostgresDatabase;
+import liquibase.ext.cosmosdb.database.CosmosLiquibaseDatabase;
+import liquibase.ext.cosmosdb.statement.CreateContainerStatement;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
+import java.util.List;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static liquibase.ext.cosmosdb.TestUtils.getChangeSets;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
class CreateContainerChangeTest extends AbstractCosmosChangeTest {
@Test
void getConfirmationMessage() {
assertThat(new CreateContainerChange().getConfirmationMessage())
- .isNotNull();
+ .isNotNull();
+ }
+
+ @Test
+ void supports() {
+ assertThat(new CreateContainerChange().supports(new CosmosLiquibaseDatabase())).isTrue();
+ assertThat(new CreateContainerChange().supports(new PostgresDatabase())).isFalse();
}
@Test
@SneakyThrows
+ @SuppressWarnings("unchecked")
void testGenerateStatements() {
- //TODO: fix
+ final List changeSets = getChangeSets("liquibase/ext/changelog.create-container.test.xml", database);
+
+ assertThat(changeSets)
+ .isNotNull()
+ .hasSize(2);
+
+ assertThat(changeSets.get(0).generateCheckSum()).isEqualTo(CheckSum.parse("8:868c41109ad4c6dd47707e31a3cab8c8"));
+ assertThat(changeSets.get(0).getChanges())
+ .hasSize(5)
+ .hasOnlyElementsOfType(CreateContainerChange.class)
+ .extracting(c -> (CreateContainerChange) c)
+ .extracting(
+ CreateContainerChange::getContainerName, CreateContainerChange::getSkipExisting, CreateContainerChange::getOptions, CreateContainerChange::getThroughput,
+ Change::generateCheckSum, c -> c.generateStatements(database).length, c -> c.generateStatements(database)[0].getClass()
+ )
+ .containsExactly(
+ tuple("minimal", null, null, null, CheckSum.parse("8:327fed49ce36964794facea53c0347d7"), 1, CreateContainerStatement.class),
+ tuple("minimal", TRUE, null, null, CheckSum.parse("8:eca3cd04f26a6b48945dfb2babf5ceda"), 1, CreateContainerStatement.class),
+ tuple("skipExisting", TRUE, null, null, CheckSum.parse("8:b3c7d43df39817432d284463344685d3"), 1, CreateContainerStatement.class),
+ tuple("skipExisting", TRUE, null, null, CheckSum.parse("8:b3c7d43df39817432d284463344685d3"), 1, CreateContainerStatement.class),
+ tuple("notSkipExisting", FALSE, null, null, CheckSum.parse("8:9d3d714841f4ebe33d6568a1d246efe9"), 1, CreateContainerStatement.class)
+ );
+
+ assertThat(changeSets.get(1).generateCheckSum()).isEqualTo(CheckSum.parse("8:d5eba9218b91327627c7174dd6630307"));
+ assertThat(changeSets.get(1).getChanges())
+ .hasSize(2)
+ .hasOnlyElementsOfType(CreateContainerChange.class)
+ .extracting(c -> (CreateContainerChange) c)
+ .extracting(
+ CreateContainerChange::getContainerName, CreateContainerChange::getSkipExisting, c -> c.getOptions().length(), CreateContainerChange::getThroughput,
+ Change::generateCheckSum, c -> c.generateStatements(database).length, c -> c.generateStatements(database)[0].getClass()
+ )
+ .containsExactly(
+ tuple("maximal", null, 1548, "500", CheckSum.parse("8:96ff35442800b98c8054b4c0b19a6817"), 1, CreateContainerStatement.class),
+ tuple("maximalAutoRU", null, 790, "{\"maxThroughput\": 8000}", CheckSum.parse("8:ee1566c77e15d830c5b90edf1576067a"), 1, CreateContainerStatement.class)
+ );
-// final List changeSets = getChangesets("liquibase/ext/changelog.create-container.test.xml", database);
-//
-// assertThat(changeSets)
-// .isNotNull()
-// .hasSize(1);
-// assertThat(changeSets.get(0).getChanges())
-// .hasSize(3)
-// .hasOnlyElementsOfType(CreateContainerChange.class);
-//
-// final CreateContainerChange ch1 = (CreateContainerChange) changeSets.get(0).getChanges().get(0);
-// assertThat(ch1.getContainerName()).isEqualTo("createCollectionWithValidatorAndOptionsTest");
-// assertThat(ch1.getPartitionKeyPath()).isNotBlank();
-// final SqlStatement[] sqlStatement1 = ch1.generateStatements(database);
-// assertThat(sqlStatement1)
-// .hasSize(1);
-// assertThat(((CreateContainerStatement) sqlStatement1[0]))
-// .hasNoNullFieldsOrProperties()
-// .hasFieldOrPropertyWithValue("collectionName", "createCollectionWithValidatorAndOptionsTest");
-//
-// final CreateContainerChange ch2 = (CreateContainerChange) changeSets.get(0).getChanges().get(1);
-// assertThat(ch2.getContainerName()).isEqualTo("createCollectionWithEmptyValidatorTest");
-// assertThat(ch2.getPartitionKeyPath()).isBlank();
-// final SqlStatement[] sqlStatement2 = ch2.generateStatements(database);
-// assertThat(sqlStatement2)
-// .hasSize(1);
-// assertThat(((CreateContainerStatement) sqlStatement2[0]))
-// .hasNoNullFieldsOrPropertiesExcept("options")
-// .hasFieldOrPropertyWithValue("collectionName", "createCollectionWithEmptyValidatorTest");
-//
-// final CreateContainerChange ch3 = (CreateContainerChange) changeSets.get(0).getChanges().get(2);
-// assertThat(ch3.getContainerName()).isEqualTo("createCollectionWithNoValidator");
-// assertThat(ch3.getPartitionKeyPath()).isBlank();
-// final SqlStatement[] sqlStatement3 = ch3.generateStatements(database);
-// assertThat(sqlStatement3)
-// .hasSize(1);
-// assertThat(((CreateContainerStatement) sqlStatement3[0]))
-// .hasNoNullFieldsOrPropertiesExcept("options")
-// .hasFieldOrPropertyWithValue("collectionName", "createCollectionWithNoValidator");
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerIfNotExistsStatementIT.java b/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerIfNotExistsStatementIT.java
deleted file mode 100644
index c026037..0000000
--- a/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerIfNotExistsStatementIT.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package liquibase.ext.cosmosdb.statement;
-
-import com.azure.cosmos.CosmosContainer;
-import liquibase.ext.cosmosdb.AbstractCosmosWithConnectionIntegrationTest;
-import lombok.SneakyThrows;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.*;
-
-class CreateContainerIfNotExistsStatementIT extends AbstractCosmosWithConnectionIntegrationTest {
- public static final String CONTAINER_NAME_1 = "containerName1";
- public static final String PARTITION_KEY_PATH_1 = "{ \"partitionKey\": {\"paths\": [\"/partitionField1\"], \"kind\": \"Hash\" } }";
-
- @SneakyThrows
- @Test
- void testExecute() {
- final CreateContainerStatement createContainerIfNotExistsStatement
- = new CreateContainerIfNotExistsStatement(CONTAINER_NAME_1, PARTITION_KEY_PATH_1);
-
- createContainerIfNotExistsStatement.execute(cosmosDatabase);
-
- final CosmosContainer cosmosContainer = cosmosDatabase.getContainer(CONTAINER_NAME_1);
-
- assertThat(cosmosContainer).isNotNull();
- assertThat(cosmosContainer.getId()).isEqualTo(CONTAINER_NAME_1);
-
- assertThatNoException().isThrownBy(() -> createContainerIfNotExistsStatement.execute(cosmosDatabase));
- }
-}
\ No newline at end of file
diff --git a/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerStatementIT.java b/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerStatementIT.java
index 062158e..7457aed 100644
--- a/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerStatementIT.java
+++ b/src/test/java/liquibase/ext/cosmosdb/statement/CreateContainerStatementIT.java
@@ -26,11 +26,41 @@ void testExecute() {
final CosmosContainer cosmosContainer = cosmosDatabase.getContainer(CONTAINER_NAME_1);
assertThat(cosmosContainer).isNotNull();
- assertThat(cosmosContainer.getId()).isEqualTo(CONTAINER_NAME_1);
+ assertThat(cosmosContainer.read().getProperties().getId()).isEqualTo(CONTAINER_NAME_1);
+ // should fail if tried once more
assertThatExceptionOfType(CosmosException.class).isThrownBy(() -> createContainerStatement.execute(cosmosDatabase));
assertThat(cosmosDatabase.getContainer("testcoll")).isNotNull();
}
+
+ @SneakyThrows
+ @Test
+ void testExecuteWithThroughput() {
+ CreateContainerStatement createContainerStatement
+ = new CreateContainerStatement("container_manual", PARTITION_KEY_PATH_1, "500");
+
+ createContainerStatement.execute(cosmosDatabase);
+
+ CosmosContainer cosmosContainer = cosmosDatabase.getContainer("container_manual");
+
+ assertThat(cosmosContainer).isNotNull();
+ assertThat(cosmosContainer.read().getProperties().getId()).isEqualTo("container_manual");
+ assertThat(cosmosContainer.readThroughput().getProperties().getManualThroughput()).isEqualTo(500);
+
+ // AutoscaleMaxThroughput
+
+ createContainerStatement
+ = new CreateContainerStatement("container_auto", PARTITION_KEY_PATH_1, "{\"maxThroughput\": 8000}");
+
+ createContainerStatement.execute(cosmosDatabase);
+
+ cosmosContainer = cosmosDatabase.getContainer("container_auto");
+
+ assertThat(cosmosContainer).isNotNull();
+ assertThat(cosmosContainer.read().getProperties().getId()).isEqualTo("container_auto");
+ assertThat(cosmosContainer.readThroughput().getProperties().getAutoscaleMaxThroughput()).isEqualTo(8000);
+
+ }
}
\ No newline at end of file
diff --git a/src/test/java/liquibase/ext/cosmosdb/statement/JsonUtilsTest.java b/src/test/java/liquibase/ext/cosmosdb/statement/JsonUtilsTest.java
index 6a57ea8..3603f4d 100644
--- a/src/test/java/liquibase/ext/cosmosdb/statement/JsonUtilsTest.java
+++ b/src/test/java/liquibase/ext/cosmosdb/statement/JsonUtilsTest.java
@@ -22,12 +22,14 @@
import com.azure.cosmos.implementation.Document;
import com.azure.cosmos.models.SqlQuerySpec;
+import com.azure.cosmos.models.ThroughputProperties;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static liquibase.ext.cosmosdb.statement.JsonUtils.mergeDocuments;
import static liquibase.ext.cosmosdb.statement.JsonUtils.orEmptyDocument;
+import static liquibase.ext.cosmosdb.statement.JsonUtils.toThroughputProperties;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -193,11 +195,28 @@ void testMergeDocuments() {
assertThat(source.get("LastName")).isEqualTo("AndersenFromSource");
assertThat(source.getList("Parents", Map.class, false)).hasSize(1);
assertThat(source.getList("Children", Map.class, false)).isNull();
- assertThat((Map)source.getObject("Address", Map.class))
+ assertThat((Map) source.getObject("Address", Map.class))
.hasFieldOrPropertyWithValue("State", "WAFromSource")
.hasFieldOrPropertyWithValue("County", "KingFromSource")
.containsKey("City").hasFieldOrPropertyWithValue("City", null);
assertThat(source.get("DestinationOnly")).isNull();
assertThat(source.get("SourceOnly")).isEqualTo(true);
}
+
+ @Test
+ @SuppressWarnings("ConstantConditions")
+ void testToThroughputProperties() {
+ assertThat(toThroughputProperties(null)).isNull();
+ assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> toThroughputProperties("{500}"))
+ .withMessage("Unable to parse JSON {500}");
+
+ assertThat(toThroughputProperties("500")).isNotNull()
+ .returns(500, ThroughputProperties::getManualThroughput)
+ .returns(0, ThroughputProperties::getAutoscaleMaxThroughput);
+
+ assertThat(toThroughputProperties(" {\"maxThroughput\": 800}")).isNotNull()
+ .returns(800, ThroughputProperties::getAutoscaleMaxThroughput);
+
+ assertThatExceptionOfType(NullPointerException.class).isThrownBy(() -> toThroughputProperties(" {\"maxThroughput\": 800}").getManualThroughput());
+ }
}
diff --git a/src/test/resources/liquibase/ext/changelog.create-container.test.xml b/src/test/resources/liquibase/ext/changelog.create-container.test.xml
index 523c567..089f862 100644
--- a/src/test/resources/liquibase/ext/changelog.create-container.test.xml
+++ b/src/test/resources/liquibase/ext/changelog.create-container.test.xml
@@ -33,7 +33,12 @@
-
+
+
+
+
+
+
@@ -44,7 +49,7 @@
- {
+ {
"id": "Container Id will be taken from: containerName attribute",
"indexingPolicy": {
"indexingMode": "Consistent",
@@ -89,9 +94,51 @@
"conflictResolutionPath": "/path"
}
}
-
+
+
+
+
+ 500
+
+
+
+
+
+
+
+
+ {
+ "indexingPolicy": {
+ "automatic": true,
+ "indexingMode": "Consistent",
+ "includedPaths": [
+ {
+ "path": "/*",
+ "indexes": [
+ {
+ "dataType": "String",
+ "precision": -1,
+ "kind": "Range"
+ }
+ ]
+ }
+ ]
+ },
+ "partitionKey": {
+ "paths": [
+ "/AccountNumber"
+ ],
+ "kind": "Hash",
+ "Version": 2
+ }
+ }
+
+
+ {"maxThroughput": 8000}
+
+
diff --git a/src/test/resources/liquibase/ext/changelog.replace-container.test.xml b/src/test/resources/liquibase/ext/changelog.replace-container.test.xml
new file mode 100644
index 0000000..3f24b44
--- /dev/null
+++ b/src/test/resources/liquibase/ext/changelog.replace-container.test.xml
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "indexingPolicy": {
+ "indexingMode": "Consistent",
+ "automatic": true,
+ "includedPaths": [
+ {
+ "path": "/*",
+ "indexes": [
+ {
+ "kind": "Range",
+ "dataType": "String",
+ "precision": -1
+ },
+ {
+ "kind": "Range",
+ "dataType": "Number",
+ "precision": -1
+ }
+ ]
+ }
+ ],
+ "excludedPaths": []
+ },
+ "partitionKey": {
+ "paths": [
+ "/accountNumber"
+ ],
+ "kind": "Hash"
+ },
+ "defaultTtl": 100,
+ "uniqueKeyPolicy": {
+ "uniqueKeys": [
+ {
+ "paths": [
+ "/transactionId"
+ ]
+ }
+ ]
+ },
+ "conflictResolutionPolicy": {
+ "mode": "LastWriterWins",
+ "conflictResolutionPath": "/path"
+ }
+ }
+
+
+
+
+ 500
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Maximum configured replaced containers
+
+
+
+
+
+
+
+
+
+
+ {"maxThroughput": 8000}
+
+
+
+
+
+
+
diff --git a/src/test/resources/liquibase/ext/test.json b/src/test/resources/liquibase/ext/test.json
new file mode 100644
index 0000000..160a0e9
--- /dev/null
+++ b/src/test/resources/liquibase/ext/test.json
@@ -0,0 +1,61 @@
+{
+ "indexingPolicy": {
+ "indexingMode": "Lazy",
+ "automatic": false,
+ "includedPaths": [
+ {
+ "path": "/*",
+ "indexes": [
+ {
+ "kind": "Range",
+ "dataType": "String",
+ "precision": -1
+ },
+ {
+ "kind": "Range",
+ "dataType": "Number",
+ "precision": -1
+ }
+ ]
+ },
+ {
+ "path": "/payload/*",
+ "indexes": [
+ {
+ "kind": "Range",
+ "dataType": "String",
+ "precision": -1
+ },
+ {
+ "kind": "Range",
+ "dataType": "Number",
+ "precision": -1
+ }
+ ]
+ }
+ ],
+ "excludedPaths": [
+ "/payload/detail/*"
+ ]
+ },
+ "partitionKey": {
+ "paths": [
+ "/accountNumber"
+ ],
+ "kind": "Hash"
+ },
+ "defaultTtl": 100,
+ "uniqueKeyPolicy": {
+ "uniqueKeys": [
+ {
+ "paths": [
+ "/transactionId"
+ ]
+ }
+ ]
+ },
+ "conflictResolutionPolicy": {
+ "mode": "LastWriterWins",
+ "conflictResolutionPath": "/path"
+ }
+}
\ No newline at end of file