Skip to content

Commit

Permalink
azurerm_cosmosdb_account - support new properties `gremlin_database…
Browse files Browse the repository at this point in the history
…` and `tables_to_restore` (#24627)

* azurerm_cosmosdb_account - support new properties

* update code

* update code

* update code

* update code

* update code
  • Loading branch information
neil-yechenwei authored Jan 31, 2024
1 parent eeaa41b commit 7f12836
Show file tree
Hide file tree
Showing 3 changed files with 333 additions and 3 deletions.
80 changes: 77 additions & 3 deletions internal/services/cosmos/cosmosdb_account_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,42 @@ func resourceCosmosDbAccount() *pluginsdk.Resource {
},
},
},

"gremlin_database": {
Type: pluginsdk.TypeList,
Optional: true,
ForceNew: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.CosmosEntityName,
},

"graph_names": {
Type: pluginsdk.TypeList,
Optional: true,
ForceNew: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validate.CosmosEntityName,
},
},
},
},
},

"tables_to_restore": {
Type: pluginsdk.TypeList,
Optional: true,
ForceNew: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validate.CosmosEntityName,
},
},
},
},
},
Expand Down Expand Up @@ -2003,14 +2039,19 @@ func expandCosmosdbAccountRestoreParameters(input []interface{}) *cosmosdb.Resto
v := input[0].(map[string]interface{})

restoreParameters := cosmosdb.RestoreParameters{
RestoreMode: pointer.To(cosmosdb.RestoreModePointInTime),
RestoreSource: pointer.To(v["source_cosmosdb_account_id"].(string)),
DatabasesToRestore: expandCosmosdbAccountDatabasesToRestore(v["database"].(*pluginsdk.Set).List()),
RestoreMode: pointer.To(cosmosdb.RestoreModePointInTime),
RestoreSource: pointer.To(v["source_cosmosdb_account_id"].(string)),
DatabasesToRestore: expandCosmosdbAccountDatabasesToRestore(v["database"].(*pluginsdk.Set).List()),
GremlinDatabasesToRestore: expandCosmosdbAccountGremlinDatabasesToRestore(v["gremlin_database"].([]interface{})),
}

restoreTimestampInUtc, _ := time.Parse(time.RFC3339, v["restore_timestamp_in_utc"].(string))
restoreParameters.SetRestoreTimestampInUtcAsTime(restoreTimestampInUtc)

if tablesToRestore := v["tables_to_restore"].([]interface{}); len(tablesToRestore) > 0 {
restoreParameters.TablesToRestore = utils.ExpandStringSlice(tablesToRestore)
}

return &restoreParameters
}

Expand All @@ -2028,6 +2069,21 @@ func expandCosmosdbAccountDatabasesToRestore(input []interface{}) *[]cosmosdb.Da
return &results
}

func expandCosmosdbAccountGremlinDatabasesToRestore(input []interface{}) *[]cosmosdb.GremlinDatabaseRestoreResource {
results := make([]cosmosdb.GremlinDatabaseRestoreResource, 0)

for _, item := range input {
v := item.(map[string]interface{})

results = append(results, cosmosdb.GremlinDatabaseRestoreResource{
DatabaseName: pointer.To(v["name"].(string)),
GraphNames: utils.ExpandStringSlice(v["graph_names"].([]interface{})),
})
}

return &results
}

func flattenCosmosdbAccountRestoreParameters(input *cosmosdb.RestoreParameters) []interface{} {
if input == nil {
return make([]interface{}, 0)
Expand All @@ -2045,8 +2101,10 @@ func flattenCosmosdbAccountRestoreParameters(input *cosmosdb.RestoreParameters)
return []interface{}{
map[string]interface{}{
"database": flattenCosmosdbAccountDatabasesToRestore(input.DatabasesToRestore),
"gremlin_database": flattenCosmosdbAccountGremlinDatabasesToRestore(input.GremlinDatabasesToRestore),
"source_cosmosdb_account_id": restoreSource,
"restore_timestamp_in_utc": restoreTimestampInUtc,
"tables_to_restore": pointer.From(input.TablesToRestore),
},
}
}
Expand All @@ -2071,6 +2129,22 @@ func flattenCosmosdbAccountDatabasesToRestore(input *[]cosmosdb.DatabaseRestoreR
return results
}

func flattenCosmosdbAccountGremlinDatabasesToRestore(input *[]cosmosdb.GremlinDatabaseRestoreResource) []interface{} {
results := make([]interface{}, 0)
if input == nil {
return results
}

for _, item := range *input {
results = append(results, map[string]interface{}{
"graph_names": utils.FlattenStringSlice(item.GraphNames),
"name": pointer.From(item.DatabaseName),
})
}

return results
}

func checkCapabilitiesCanBeUpdated(kind string, oldCapabilities *[]cosmosdb.Capability, newCapabilities *[]cosmosdb.Capability) bool {
// The feedback from service team : capabilities that can be added to an existing account
canBeAddedCaps := []string{
Expand Down
244 changes: 244 additions & 0 deletions internal/services/cosmos/cosmosdb_account_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,36 @@ func TestAccCosmosDBAccount_restoreCreateMode(t *testing.T) {
})
}

func TestAccCosmosDBAccount_tablesToRestore(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_cosmosdb_account", "test")
r := CosmosDBAccountResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.tablesToRestore(data, cosmosdb.DatabaseAccountKindGlobalDocumentDB, cosmosdb.DefaultConsistencyLevelStrong),
Check: acceptance.ComposeAggregateTestCheckFunc(
checkAccCosmosDBAccount_basic(data, cosmosdb.DefaultConsistencyLevelStrong, 1),
),
},
data.ImportStep(),
})
}

func TestAccCosmosDBAccount_gremlinDatabasesToRestore(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_cosmosdb_account", "test")
r := CosmosDBAccountResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.gremlinDatabasesToRestore(data, cosmosdb.DatabaseAccountKindGlobalDocumentDB, cosmosdb.DefaultConsistencyLevelStrong),
Check: acceptance.ComposeAggregateTestCheckFunc(
checkAccCosmosDBAccount_basic(data, cosmosdb.DefaultConsistencyLevelStrong, 1),
),
},
data.ImportStep(),
})
}

// todo remove for 4.0
func TestAccCosmosDBAccount_ipRangeFiltersThreePointOh(t *testing.T) {
if features.FourPointOhBeta() {
Expand Down Expand Up @@ -4117,6 +4147,220 @@ resource "azurerm_cosmosdb_account" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, string(kind), string(consistency))
}

func (CosmosDBAccountResource) tablesToRestore(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-cosmos-%d"
location = "%s"
}
resource "azurerm_cosmosdb_account" "test1" {
name = "acctest-ca-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
capabilities {
name = "EnableTable"
}
consistency_policy {
consistency_level = "Strong"
}
geo_location {
location = azurerm_resource_group.test.location
failover_priority = 0
}
backup {
type = "Continuous"
}
}
resource "azurerm_cosmosdb_table" "test" {
name = "acctest-sqltable-%d"
resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name
account_name = azurerm_cosmosdb_account.test1.name
}
resource "azurerm_cosmosdb_table" "test2" {
name = "acctest-sqltable2-%d"
resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name
account_name = azurerm_cosmosdb_account.test1.name
depends_on = [azurerm_cosmosdb_table.test]
}
data "azurerm_cosmosdb_restorable_database_accounts" "test" {
name = azurerm_cosmosdb_account.test1.name
location = azurerm_resource_group.test.location
depends_on = [azurerm_cosmosdb_table.test2]
}
resource "azurerm_cosmosdb_account" "test" {
name = "acctest-ca2-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
offer_type = "Standard"
kind = "%s"
capabilities {
name = "EnableTable"
}
consistency_policy {
consistency_level = "%s"
}
geo_location {
location = azurerm_resource_group.test.location
failover_priority = 0
}
backup {
type = "Continuous"
}
create_mode = "Restore"
restore {
source_cosmosdb_account_id = data.azurerm_cosmosdb_restorable_database_accounts.test.accounts[0].id
restore_timestamp_in_utc = timeadd(timestamp(), "-1s")
tables_to_restore = [azurerm_cosmosdb_table.test.name, azurerm_cosmosdb_table.test2.name]
}
// As "restore_timestamp_in_utc" is retrieved dynamically, so it would cause diff when tf plan. So we have to ignore it here.
lifecycle {
ignore_changes = [
restore.0.restore_timestamp_in_utc
]
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, string(kind), string(consistency))
}

func (CosmosDBAccountResource) gremlinDatabasesToRestore(data acceptance.TestData, kind cosmosdb.DatabaseAccountKind, consistency cosmosdb.DefaultConsistencyLevel) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-cosmos-%d"
location = "%s"
}
resource "azurerm_cosmosdb_account" "test1" {
name = "acctest-ca-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
capabilities {
name = "EnableGremlin"
}
consistency_policy {
consistency_level = "Strong"
}
geo_location {
location = azurerm_resource_group.test.location
failover_priority = 0
}
backup {
type = "Continuous"
}
}
resource "azurerm_cosmosdb_gremlin_database" "test" {
name = "acctest-gremlindb-%d"
resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name
account_name = azurerm_cosmosdb_account.test1.name
}
resource "azurerm_cosmosdb_gremlin_graph" "test" {
name = "acctest-CGRPC-%d"
resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name
account_name = azurerm_cosmosdb_account.test1.name
database_name = azurerm_cosmosdb_gremlin_database.test.name
partition_key_path = "/test"
throughput = 400
}
resource "azurerm_cosmosdb_gremlin_graph" "test2" {
name = "acctest-CGRPC2-%d"
resource_group_name = azurerm_cosmosdb_account.test1.resource_group_name
account_name = azurerm_cosmosdb_account.test1.name
database_name = azurerm_cosmosdb_gremlin_database.test.name
partition_key_path = "/test2"
throughput = 500
depends_on = [azurerm_cosmosdb_gremlin_graph.test]
}
data "azurerm_cosmosdb_restorable_database_accounts" "test" {
name = azurerm_cosmosdb_account.test1.name
location = azurerm_resource_group.test.location
depends_on = [azurerm_cosmosdb_gremlin_graph.test2]
}
resource "azurerm_cosmosdb_account" "test" {
name = "acctest-ca2-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
offer_type = "Standard"
kind = "%s"
capabilities {
name = "EnableGremlin"
}
consistency_policy {
consistency_level = "%s"
}
geo_location {
location = azurerm_resource_group.test.location
failover_priority = 0
}
backup {
type = "Continuous"
}
create_mode = "Restore"
restore {
source_cosmosdb_account_id = data.azurerm_cosmosdb_restorable_database_accounts.test.accounts[0].id
restore_timestamp_in_utc = timeadd(timestamp(), "-1s")
gremlin_database {
name = azurerm_cosmosdb_gremlin_database.test.name
graph_names = [azurerm_cosmosdb_gremlin_graph.test.name, azurerm_cosmosdb_gremlin_graph.test2.name]
}
}
// As "restore_timestamp_in_utc" is retrieved dynamically, so it would cause diff when tf plan. So we have to ignore it here.
lifecycle {
ignore_changes = [
restore.0.restore_timestamp_in_utc
]
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, string(kind), string(consistency))
}

func (r CosmosDBAccountResource) ipRangeFilters(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
Expand Down
Loading

0 comments on commit 7f12836

Please sign in to comment.