diff --git a/azurerm/internal/services/cosmos/common/indexing_policy.go b/azurerm/internal/services/cosmos/common/indexing_policy.go index 4ae71e35e790..fa4b506471e4 100644 --- a/azurerm/internal/services/cosmos/common/indexing_policy.go +++ b/azurerm/internal/services/cosmos/common/indexing_policy.go @@ -45,7 +45,7 @@ func expandAzureRmCosmosDBIndexingPolicyExcludedPaths(input []interface{}) *[]do return &paths } -func expandAzureRmCosmosDBIndexingPolicyCompositeIndexes(input []interface{}) *[][]documentdb.CompositePath { +func ExpandAzureRmCosmosDBIndexingPolicyCompositeIndexes(input []interface{}) *[][]documentdb.CompositePath { indexes := make([][]documentdb.CompositePath, 0) for _, i := range input { @@ -83,7 +83,7 @@ func ExpandAzureRmCosmosDbIndexingPolicy(d *pluginsdk.ResourceData) *documentdb. } if v, ok := input["composite_index"].([]interface{}); ok { - policy.CompositeIndexes = expandAzureRmCosmosDBIndexingPolicyCompositeIndexes(v) + policy.CompositeIndexes = ExpandAzureRmCosmosDBIndexingPolicyCompositeIndexes(v) } return policy } @@ -131,7 +131,7 @@ func flattenCosmosDBIndexingPolicyCompositeIndex(input []documentdb.CompositePat return indexPairs } -func flattenCosmosDBIndexingPolicyCompositeIndexes(input *[][]documentdb.CompositePath) []interface{} { +func FlattenCosmosDBIndexingPolicyCompositeIndexes(input *[][]documentdb.CompositePath) []interface{} { if input == nil { return []interface{}{} } @@ -173,7 +173,7 @@ func FlattenAzureRmCosmosDbIndexingPolicy(indexingPolicy *documentdb.IndexingPol result["indexing_mode"] = strings.Title(string(indexingPolicy.IndexingMode)) result["included_path"] = flattenCosmosDBIndexingPolicyIncludedPaths(indexingPolicy.IncludedPaths) result["excluded_path"] = flattenCosmosDBIndexingPolicyExcludedPaths(indexingPolicy.ExcludedPaths) - result["composite_index"] = flattenCosmosDBIndexingPolicyCompositeIndexes(indexingPolicy.CompositeIndexes) + result["composite_index"] = FlattenCosmosDBIndexingPolicyCompositeIndexes(indexingPolicy.CompositeIndexes) results = append(results, result) return results diff --git a/azurerm/internal/services/cosmos/common/schema.go b/azurerm/internal/services/cosmos/common/schema.go index d05eafdd8dec..dc04eacb206d 100644 --- a/azurerm/internal/services/cosmos/common/schema.go +++ b/azurerm/internal/services/cosmos/common/schema.go @@ -150,41 +150,7 @@ func CosmosDbIndexingPolicySchema() *pluginsdk.Schema { }, }, }, - "composite_index": { - Type: pluginsdk.TypeList, - Optional: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "index": { - Type: pluginsdk.TypeList, - MinItems: 1, - Required: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "path": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - // `order` case changes from 2020-04-01 to 2021-01-15, issue opened:https://github.com/Azure/azure-rest-api-specs/issues/14051 - // todo: change to SDK constants and remove translation code in 3.0 - "order": { - Type: pluginsdk.TypeString, - Required: true, - // Workaround for Azure/azure-rest-api-specs#11222 - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice( - []string{ - "Ascending", - "Descending", - }, false), - }, - }, - }, - }, - }, - }, - }, + "composite_index": CosmosDbIndexingPolicyCompositeIndexSchema(), }, }, } @@ -223,3 +189,41 @@ func ConflictResolutionPolicy() *pluginsdk.Schema { }, } } + +func CosmosDbIndexingPolicyCompositeIndexSchema() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "index": { + Type: pluginsdk.TypeList, + MinItems: 1, + Required: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "path": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + // `order` case changes from 2020-04-01 to 2021-01-15, issue opened:https://github.com/Azure/azure-rest-api-specs/issues/14051 + // todo: change to SDK constants and remove translation code in 3.0 + "order": { + Type: pluginsdk.TypeString, + Required: true, + // Workaround for Azure/azure-rest-api-specs#11222 + DiffSuppressFunc: suppress.CaseDifference, + ValidateFunc: validation.StringInSlice( + []string{ + "Ascending", + "Descending", + }, false), + }, + }, + }, + }, + }, + }, + } +} diff --git a/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource.go b/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource.go index 28115d2c30b2..0d341f11fd39 100644 --- a/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource.go +++ b/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource.go @@ -90,10 +90,18 @@ func resourceCosmosDbGremlinGraph() *pluginsdk.Resource { ValidateFunc: validation.StringIsNotEmpty, }, + "partition_key_version": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 2), + }, + "index_policy": { Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, + Optional: true, + Computed: true, + MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "automatic": { @@ -118,6 +126,7 @@ func resourceCosmosDbGremlinGraph() *pluginsdk.Resource { "included_paths": { Type: pluginsdk.TypeSet, Optional: true, + Computed: true, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringIsNotEmpty, @@ -128,12 +137,15 @@ func resourceCosmosDbGremlinGraph() *pluginsdk.Resource { "excluded_paths": { Type: pluginsdk.TypeSet, Optional: true, + Computed: true, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringIsNotEmpty, }, Set: pluginsdk.HashString, }, + + "composite_index": common.CosmosDbIndexingPolicyCompositeIndexSchema(), }, }, }, @@ -200,6 +212,10 @@ func resourceCosmosDbGremlinGraphCreate(d *pluginsdk.ResourceData, meta interfac if partitionkeypaths != "" { db.GremlinGraphCreateUpdateProperties.Resource.PartitionKey = &documentdb.ContainerPartitionKey{ Paths: &[]string{partitionkeypaths}, + Kind: documentdb.PartitionKindHash, + } + if partitionKeyVersion, ok := d.GetOk("partition_key_version"); ok { + db.GremlinGraphCreateUpdateProperties.Resource.PartitionKey.Version = utils.Int32(int32(partitionKeyVersion.(int))) } } @@ -278,6 +294,11 @@ func resourceCosmosDbGremlinGraphUpdate(d *pluginsdk.ResourceData, meta interfac if partitionkeypaths != "" { db.GremlinGraphCreateUpdateProperties.Resource.PartitionKey = &documentdb.ContainerPartitionKey{ Paths: &[]string{partitionkeypaths}, + Kind: documentdb.PartitionKindHash, + } + + if partitionKeyVersion, ok := d.GetOk("partition_key_version"); ok { + db.GremlinGraphCreateUpdateProperties.Resource.PartitionKey.Version = utils.Int32(int32(partitionKeyVersion.(int))) } } @@ -354,6 +375,10 @@ func resourceCosmosDbGremlinGraphRead(d *pluginsdk.ResourceData, meta interface{ d.Set("partition_key_path", (*paths)[0]) } } + + if version := pk.Version; version != nil { + d.Set("partition_key_version", version) + } } if ip := props.IndexingPolicy; ip != nil { @@ -432,6 +457,9 @@ func expandAzureRmCosmosDbGrelinGraphIndexingPolicy(d *pluginsdk.ResourceData) * IncludedPaths: expandAzureRmCosmosDbGrelimGraphIncludedPath(input), ExcludedPaths: expandAzureRmCosmosDbGremlinGraphExcludedPath(input), } + if v, ok := input["composite_index"].([]interface{}); ok { + policy.CompositeIndexes = common.ExpandAzureRmCosmosDBIndexingPolicyCompositeIndexes(v) + } if automatic, ok := input["automatic"].(bool); ok { policy.Automatic = utils.Bool(automatic) @@ -503,6 +531,7 @@ func flattenAzureRmCosmosDBGremlinGraphIndexingPolicy(input *documentdb.Indexing indexPolicy["indexing_mode"] = strings.Title(string(input.IndexingMode)) indexPolicy["included_paths"] = pluginsdk.NewSet(pluginsdk.HashString, flattenAzureRmCosmosDBGremlinGraphIncludedPaths(input.IncludedPaths)) indexPolicy["excluded_paths"] = pluginsdk.NewSet(pluginsdk.HashString, flattenAzureRmCosmosDBGremlinGraphExcludedPaths(input.ExcludedPaths)) + indexPolicy["composite_index"] = common.FlattenCosmosDBIndexingPolicyCompositeIndexes(input.CompositeIndexes) return []interface{}{indexPolicy} } diff --git a/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource_test.go b/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource_test.go index 6457b6b50ce7..b1b4f9f8a31d 100644 --- a/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource_test.go +++ b/azurerm/internal/services/cosmos/cosmosdb_gremlin_graph_resource_test.go @@ -76,6 +76,13 @@ func TestAccCosmosDbGremlinGraph_indexPolicy(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.indexPolicyCompositeIndex(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), }) } @@ -137,6 +144,23 @@ func TestAccCosmosDbGremlinGraph_autoscale(t *testing.T) { }) } +func TestAccCosmosDbGremlinGraph_partition_key_version(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_cosmosdb_gremlin_graph", "test") + r := CosmosGremlinGraphResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + + Config: r.partition_key_version(data, 2), + Check: acceptance.ComposeAggregateTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("partition_key_version").HasValue("2"), + ), + }, + data.ImportStep(), + }) +} + func (t CosmosGremlinGraphResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.GremlinGraphID(state.ID) if err != nil { @@ -162,13 +186,6 @@ resource "azurerm_cosmosdb_gremlin_graph" "test" { database_name = azurerm_cosmosdb_gremlin_database.test.name partition_key_path = "/test" throughput = 400 - - index_policy { - automatic = true - indexing_mode = "Consistent" - included_paths = ["/*"] - excluded_paths = ["/\"_etag\"/?"] - } } `, CosmosGremlinDatabaseResource{}.basic(data), data.RandomInteger) } @@ -183,13 +200,6 @@ resource "azurerm_cosmosdb_gremlin_graph" "import" { account_name = azurerm_cosmosdb_account.test.name database_name = azurerm_cosmosdb_gremlin_database.test.name partition_key_path = azurerm_cosmosdb_gremlin_graph.test.partition_key_path - - index_policy { - automatic = true - indexing_mode = "Consistent" - included_paths = ["/*"] - excluded_paths = ["/\"_etag\"/?"] - } } `, r.basic(data)) } @@ -246,6 +256,53 @@ resource "azurerm_cosmosdb_gremlin_graph" "test" { `, CosmosGremlinDatabaseResource{}.basic(data), data.RandomInteger) } +func (CosmosGremlinGraphResource) indexPolicyCompositeIndex(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_cosmosdb_gremlin_graph" "test" { + name = "acctest-CGRPC-%[2]d" + resource_group_name = azurerm_cosmosdb_account.test.resource_group_name + account_name = azurerm_cosmosdb_account.test.name + database_name = azurerm_cosmosdb_gremlin_database.test.name + partition_key_path = "/test" + throughput = 400 + + index_policy { + automatic = true + indexing_mode = "Consistent" + + composite_index { + index { + path = "/path1" + order = "Ascending" + } + index { + path = "/path2" + order = "Descending" + } + } + + composite_index { + index { + path = "/path3" + order = "Ascending" + } + index { + path = "/path4" + order = "Descending" + } + } + } + + conflict_resolution_policy { + mode = "LastWriterWins" + conflict_resolution_path = "/_ts" + } +} +`, CosmosGremlinDatabaseResource{}.basic(data), data.RandomInteger) +} + func (CosmosGremlinGraphResource) update(data acceptance.TestData, throughput int, defaultTTL int) string { return fmt.Sprintf(` %[1]s @@ -297,3 +354,18 @@ resource "azurerm_cosmosdb_gremlin_graph" "test" { } `, CosmosGremlinDatabaseResource{}.basic(data), data.RandomInteger, maxThroughput) } + +func (CosmosGremlinGraphResource) partition_key_version(data acceptance.TestData, version int) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_cosmosdb_gremlin_graph" "test" { + name = "acctest-CGRPC-%[2]d" + resource_group_name = azurerm_cosmosdb_account.test.resource_group_name + account_name = azurerm_cosmosdb_account.test.name + database_name = azurerm_cosmosdb_gremlin_database.test.name + partition_key_path = "/test" + partition_key_version = %[3]d +} +`, CosmosGremlinDatabaseResource{}.basic(data), data.RandomInteger, version) +} diff --git a/website/docs/r/cosmosdb_gremlin_graph.html.markdown b/website/docs/r/cosmosdb_gremlin_graph.html.markdown index be2a52956ef9..1a25e90efaad 100644 --- a/website/docs/r/cosmosdb_gremlin_graph.html.markdown +++ b/website/docs/r/cosmosdb_gremlin_graph.html.markdown @@ -66,6 +66,8 @@ The following arguments are supported: * `partition_key_path` - (Required) Define a partition key. Changing this forces a new resource to be created. +* `partition_key_version` - (Optional) Define a partition key version. Changing this forces a new resource to be created. Possible values are `1 `and `2`. This should be set to `2` in order to use large partition keys. + * `throughput` - (Optional) The throughput of the Gremlin graph (RU/s). Must be set in increments of `100`. The minimum value is `400`. This must be set upon database creation otherwise it cannot be updated without a manual terraform destroy-apply. * `default_ttl` - (Optional) The default time to live (TTL) of the Gremlin graph. If the value is missing or set to "-1", items don’t expire. @@ -98,6 +100,10 @@ An `index_policy` block supports the following: * `excluded_paths` - (Optional) List of paths to exclude from indexing. Required if `indexing_mode` is `Consistent` or `Lazy`. +* `composite_index` - (Optional) One or more `composite_index` blocks as defined below. + +--- + An `conflict_resolution_policy` block supports the following: * `mode` - (Required) Indicates the conflict resolution mode. Possible values include: `LastWriterWins`, `Custom`. @@ -106,10 +112,27 @@ An `conflict_resolution_policy` block supports the following: * `conflict_resolution_procedure` - (Optional) The procedure to resolve conflicts in the case of custom mode. +--- + An `unique_key` block supports the following: * `paths` - (Required) A list of paths to use for this unique key. +--- + +A `composite_index` block supports the following: + +* `index` - One or more `index` blocks as defined below. + +--- + +An `index` block supports the following: + +* `path` - Path for which the indexing behaviour applies to. + +* `order` - Order of the index. Possible values are `Ascending` or `Descending`. + + ## Attributes Reference The following attributes are exported: