diff --git a/azurerm/resource_arm_cosmosdb_cassandra_keyspace.go b/azurerm/resource_arm_cosmosdb_cassandra_keyspace.go index 15a6f77ae749..001ff878b778 100644 --- a/azurerm/resource_arm_cosmosdb_cassandra_keyspace.go +++ b/azurerm/resource_arm_cosmosdb_cassandra_keyspace.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "strconv" "time" "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb" @@ -20,6 +21,7 @@ func resourceArmCosmosDbCassandraKeyspace() *schema.Resource { return &schema.Resource{ Create: resourceArmCosmosDbCassandraKeyspaceCreate, Read: resourceArmCosmosDbCassandraKeyspaceRead, + Update: resourceArmCosmosDbCassandraKeyspaceUpdate, Delete: resourceArmCosmosDbCassandraKeyspaceDelete, Importer: &schema.ResourceImporter{ @@ -49,6 +51,13 @@ func resourceArmCosmosDbCassandraKeyspace() *schema.Resource { ForceNew: true, ValidateFunc: validate.CosmosAccountName, }, + + "throughput": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validate.CosmosThroughput, + }, }, } } @@ -62,7 +71,7 @@ func resourceArmCosmosDbCassandraKeyspaceCreate(d *schema.ResourceData, meta int resourceGroup := d.Get("resource_group_name").(string) account := d.Get("account_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if features.ShouldResourcesBeImported() { existing, err := client.GetCassandraKeyspace(ctx, resourceGroup, account, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -87,6 +96,12 @@ func resourceArmCosmosDbCassandraKeyspaceCreate(d *schema.ResourceData, meta int }, } + if throughput, hasThroughput := d.GetOk("throughput"); hasThroughput { + db.CassandraKeyspaceCreateUpdateProperties.Options = map[string]*string{ + "throughput": utils.String(strconv.Itoa(throughput.(int))), + } + } + future, err := client.CreateUpdateCassandraKeyspace(ctx, resourceGroup, account, name, db) if err != nil { return fmt.Errorf("Error issuing create/update request for Cosmos Cassandra Keyspace %s (Account %s): %+v", name, account, err) @@ -110,6 +125,59 @@ func resourceArmCosmosDbCassandraKeyspaceCreate(d *schema.ResourceData, meta int return resourceArmCosmosDbCassandraKeyspaceRead(d, meta) } +func resourceArmCosmosDbCassandraKeyspaceUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Cosmos.DatabaseClient + ctx, cancel := timeouts.ForCreate(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseCosmosKeyspaceID(d.Id()) + if err != nil { + return err + } + + db := documentdb.CassandraKeyspaceCreateUpdateParameters{ + CassandraKeyspaceCreateUpdateProperties: &documentdb.CassandraKeyspaceCreateUpdateProperties{ + Resource: &documentdb.CassandraKeyspaceResource{ + ID: &id.Keyspace, + }, + Options: map[string]*string{}, + }, + } + + future, err := client.CreateUpdateCassandraKeyspace(ctx, id.ResourceGroup, id.Account, id.Keyspace, db) + if err != nil { + return fmt.Errorf("Error issuing create/update request for Cosmos Cassandra Keyspace %s (Account %s): %+v", id.ResourceGroup, id.Account, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on create/update future for Cosmos Cassandra Keyspace %s (Account %s): %+v", id.ResourceGroup, id.Account, err) + } + + if d.HasChange("throughput") { + throughputParameters := documentdb.ThroughputUpdateParameters{ + ThroughputUpdateProperties: &documentdb.ThroughputUpdateProperties{ + Resource: &documentdb.ThroughputResource{ + Throughput: utils.Int32(int32(d.Get("throughput").(int))), + }, + }, + } + + throughputFuture, err := client.UpdateCassandraKeyspaceThroughput(ctx, id.ResourceGroup, id.Account, id.Keyspace, throughputParameters) + if err != nil { + if response.WasNotFound(throughputFuture.Response()) { + return fmt.Errorf("Error setting Throughput for Cosmos Cassandra Keyspace %s (Account %s): %+v - "+ + "If the collection has not been created with an initial throughput, you cannot configure it later.", id.Keyspace, id.Account, err) + } + } + + if err = throughputFuture.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on ThroughputUpdate future for Cosmos Cassandra Keyspace %s (Account %s): %+v", id.Keyspace, id.Account, err) + } + } + + return resourceArmCosmosDbCassandraKeyspaceRead(d, meta) +} + func resourceArmCosmosDbCassandraKeyspaceRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Cosmos.DatabaseClient ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) @@ -137,6 +205,17 @@ func resourceArmCosmosDbCassandraKeyspaceRead(d *schema.ResourceData, meta inter d.Set("name", props.ID) } + throughputResp, err := client.GetCassandraKeyspaceThroughput(ctx, id.ResourceGroup, id.Account, id.Keyspace) + if err != nil { + if !utils.ResponseWasNotFound(throughputResp.Response) { + return fmt.Errorf("Error reading Throughput on Cosmos Cassandra Keyspace %s (Account %s): %+v", id.Keyspace, id.Account, err) + } else { + d.Set("throughput", nil) + } + } else { + d.Set("throughput", throughputResp.Throughput) + } + return nil } diff --git a/azurerm/resource_arm_cosmosdb_cassandra_keyspace_test.go b/azurerm/resource_arm_cosmosdb_cassandra_keyspace_test.go index 7c0b24b1b330..9d6ea9afb271 100644 --- a/azurerm/resource_arm_cosmosdb_cassandra_keyspace_test.go +++ b/azurerm/resource_arm_cosmosdb_cassandra_keyspace_test.go @@ -35,6 +35,68 @@ func TestAccAzureRMCosmosDbCassandraKeyspace_basic(t *testing.T) { }) } +func TestAccAzureRMCosmosDbCassandraKeyspace_complete(t *testing.T) { + ri := tf.AccRandTimeInt() + resourceName := "azurerm_cosmosdb_cassandra_keyspace.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMCosmosDbCassandraKeyspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMCosmosDbCassandraKeyspace_throughput(ri, testLocation(), 700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbCassandraKeyspaceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMCosmosDbCassandraKeyspace_update(t *testing.T) { + ri := tf.AccRandTimeInt() + resourceName := "azurerm_cosmosdb_cassandra_keyspace.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMCosmosDbCassandraKeyspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMCosmosDbCassandraKeyspace_throughput(ri, testLocation(), 700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbCassandraKeyspaceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAzureRMCosmosDbCassandraKeyspace_throughput(ri, testLocation(), 1700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbCassandraKeyspaceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "1700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMCosmosDbCassandraKeyspaceDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*ArmClient).Cosmos.DatabaseClient ctx := testAccProvider.Meta().(*ArmClient).StopContext @@ -102,3 +164,17 @@ resource "azurerm_cosmosdb_cassandra_keyspace" "test" { } `, testAccAzureRMCosmosDBAccount_capabilityCassandra(rInt, location), rInt) } + +func testAccAzureRMCosmosDbCassandraKeyspace_throughput(rInt int, location string, throughput int) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_cosmosdb_cassandra_keyspace" "test" { + name = "acctest-%[2]d" + resource_group_name = "${azurerm_cosmosdb_account.test.resource_group_name}" + account_name = "${azurerm_cosmosdb_account.test.name}" + + throughput = %[3]d +} +`, testAccAzureRMCosmosDBAccount_capabilityCassandra(rInt, location), rInt, throughput) +} diff --git a/azurerm/resource_arm_cosmosdb_mongo_collection.go b/azurerm/resource_arm_cosmosdb_mongo_collection.go index 04e134541abe..9ce29da9384c 100644 --- a/azurerm/resource_arm_cosmosdb_mongo_collection.go +++ b/azurerm/resource_arm_cosmosdb_mongo_collection.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "net/http" "strconv" "strings" "time" @@ -238,8 +237,7 @@ func resourceArmCosmosDbMongoCollectionUpdate(d *schema.ResourceData, meta inter throughputFuture, err := client.UpdateMongoDBCollectionThroughput(ctx, id.ResourceGroup, id.Account, id.Database, id.Collection, throughputParameters) if err != nil { - if throughputFuture.Response().StatusCode == http.StatusNotFound { - d.Set("throughput", nil) + if response.WasNotFound(throughputFuture.Response()) { return fmt.Errorf("Error setting Throughput for Cosmos MongoDB Collection %s (Account %s, Database %s): %+v - "+ "If the collection has not been created with an initial throughput, you cannot configure it later.", id.Collection, id.Account, id.Database, err) } diff --git a/azurerm/resource_arm_cosmosdb_mongo_database.go b/azurerm/resource_arm_cosmosdb_mongo_database.go index 2f2e9cbb5eb5..f7943bf07c62 100644 --- a/azurerm/resource_arm_cosmosdb_mongo_database.go +++ b/azurerm/resource_arm_cosmosdb_mongo_database.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "net/http" "strconv" "time" @@ -165,8 +164,7 @@ func resourceArmCosmosDbMongoDatabaseUpdate(d *schema.ResourceData, meta interfa throughputFuture, err := client.UpdateMongoDBDatabaseThroughput(ctx, id.ResourceGroup, id.Account, id.Database, throughputParameters) if err != nil { - if throughputFuture.Response().StatusCode == http.StatusNotFound { - d.Set("throughput", nil) + if response.WasNotFound(throughputFuture.Response()) { return fmt.Errorf("Error setting Throughput for Cosmos MongoDB Database %s (Account %s): %+v - "+ "If the collection has not been created with an initial throughput, you cannot configure it later.", id.Database, id.Account, err) } diff --git a/azurerm/resource_arm_cosmosdb_sql_container.go b/azurerm/resource_arm_cosmosdb_sql_container.go index eda5c75a58e2..ba2e80014bef 100644 --- a/azurerm/resource_arm_cosmosdb_sql_container.go +++ b/azurerm/resource_arm_cosmosdb_sql_container.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "strconv" "time" "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb" @@ -20,6 +21,7 @@ func resourceArmCosmosDbSQLContainer() *schema.Resource { return &schema.Resource{ Create: resourceArmCosmosDbSQLContainerCreate, Read: resourceArmCosmosDbSQLContainerRead, + Update: resourceArmCosmosDbSQLContainerUpdate, Delete: resourceArmCosmosDbSQLContainerDelete, Importer: &schema.ResourceImporter{ @@ -64,6 +66,13 @@ func resourceArmCosmosDbSQLContainer() *schema.Resource { ValidateFunc: validate.NoEmptyStrings, }, + "throughput": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validate.CosmosThroughput, + }, + "unique_key": { Type: schema.TypeSet, Optional: true, @@ -97,7 +106,7 @@ func resourceArmCosmosDbSQLContainerCreate(d *schema.ResourceData, meta interfac account := d.Get("account_name").(string) partitionkeypaths := d.Get("partition_key_path").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if features.ShouldResourcesBeImported() { existing, err := client.GetSQLContainer(ctx, resourceGroup, account, database, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -135,6 +144,12 @@ func resourceArmCosmosDbSQLContainerCreate(d *schema.ResourceData, meta interfac } } + if throughput, hasThroughput := d.GetOk("throughput"); hasThroughput { + db.SQLContainerCreateUpdateProperties.Options = map[string]*string{ + "throughput": utils.String(strconv.Itoa(throughput.(int))), + } + } + future, err := client.CreateUpdateSQLContainer(ctx, resourceGroup, account, database, name, db) if err != nil { return fmt.Errorf("Error issuing create/update request for Cosmos SQL Container %s (Account: %s, Database:%s): %+v", name, account, database, err) @@ -158,6 +173,74 @@ func resourceArmCosmosDbSQLContainerCreate(d *schema.ResourceData, meta interfac return resourceArmCosmosDbSQLContainerRead(d, meta) } +func resourceArmCosmosDbSQLContainerUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Cosmos.DatabaseClient + ctx, cancel := timeouts.ForCreate(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseCosmosDatabaseContainerID(d.Id()) + if err != nil { + return err + } + + partitionkeypaths := d.Get("partition_key_path").(string) + + db := documentdb.SQLContainerCreateUpdateParameters{ + SQLContainerCreateUpdateProperties: &documentdb.SQLContainerCreateUpdateProperties{ + Resource: &documentdb.SQLContainerResource{ + ID: &id.Container, + }, + Options: map[string]*string{}, + }, + } + + if partitionkeypaths != "" { + db.SQLContainerCreateUpdateProperties.Resource.PartitionKey = &documentdb.ContainerPartitionKey{ + Paths: &[]string{partitionkeypaths}, + Kind: documentdb.PartitionKindHash, + } + } + + if keys := expandCosmosSQLContainerUniqueKeys(d.Get("unique_key").(*schema.Set)); keys != nil { + db.SQLContainerCreateUpdateProperties.Resource.UniqueKeyPolicy = &documentdb.UniqueKeyPolicy{ + UniqueKeys: keys, + } + } + + future, err := client.CreateUpdateSQLContainer(ctx, id.Container, id.Account, id.Database, id.Container, db) + if err != nil { + return fmt.Errorf("Error issuing create/update request for Cosmos SQL Container %s (Account: %s, Database:%s): %+v", id.Container, id.Account, id.Database, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on create/update future for Cosmos SQL Container %s (Account: %s, Database:%s): %+v", id.Container, id.Account, id.Database, err) + } + + if d.HasChange("throughput") { + throughputParameters := documentdb.ThroughputUpdateParameters{ + ThroughputUpdateProperties: &documentdb.ThroughputUpdateProperties{ + Resource: &documentdb.ThroughputResource{ + Throughput: utils.Int32(int32(d.Get("throughput").(int))), + }, + }, + } + + throughputFuture, err := client.UpdateSQLContainerThroughput(ctx, id.ResourceGroup, id.Account, id.Database, id.Container, throughputParameters) + if err != nil { + if response.WasNotFound(throughputFuture.Response()) { + return fmt.Errorf("Error setting Throughput for Cosmos SQL Container %s (Account: %s, Database:%s): %+v - "+ + "If the collection has not been created with an initial throughput, you cannot configure it later.", id.Container, id.Account, id.Database, err) + } + } + + if err = throughputFuture.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on ThroughputUpdate future for Cosmos Container %s (Account: %s, Database:%s): %+v", id.Container, id.Account, id.Database, err) + } + } + + return resourceArmCosmosDbSQLContainerRead(d, meta) +} + func resourceArmCosmosDbSQLContainerRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Cosmos.DatabaseClient ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) @@ -202,6 +285,17 @@ func resourceArmCosmosDbSQLContainerRead(d *schema.ResourceData, meta interface{ } } + throughputResp, err := client.GetSQLContainerThroughput(ctx, id.ResourceGroup, id.Account, id.Database, id.Container) + if err != nil { + if !utils.ResponseWasNotFound(throughputResp.Response) { + return fmt.Errorf("Error reading Throughput on Cosmos SQL Container '%s' (Account: %s, Database:%s) ID: %v", id.Container, id.Account, id.Database, err) + } else { + d.Set("throughput", nil) + } + } else { + d.Set("throughput", throughputResp.Throughput) + } + return nil } diff --git a/azurerm/resource_arm_cosmosdb_sql_container_test.go b/azurerm/resource_arm_cosmosdb_sql_container_test.go index 4dfb278f64c7..39040d7e664a 100644 --- a/azurerm/resource_arm_cosmosdb_sql_container_test.go +++ b/azurerm/resource_arm_cosmosdb_sql_container_test.go @@ -72,16 +72,23 @@ func TestAccAzureRMCosmosDbSqlContainer_update(t *testing.T) { Steps: []resource.TestStep{ { - Config: testAccAzureRMCosmosDbSqlContainer_basic(ri, testLocation()), + Config: testAccAzureRMCosmosDbSqlContainer_complete(ri, testLocation()), Check: resource.ComposeAggregateTestCheckFunc( testCheckAzureRMCosmosDbSqlContainerExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "600"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { - Config: testAccAzureRMCosmosDbSqlContainer_complete(ri, testLocation()), + Config: testAccAzureRMCosmosDbSqlContainer_update(ri, testLocation()), Check: resource.ComposeAggregateTestCheckFunc( testCheckAzureRMCosmosDbSqlContainerExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "400"), ), }, { @@ -179,6 +186,26 @@ resource "azurerm_cosmosdb_sql_container" "test" { unique_key { paths = ["/definition/id1", "/definition/id2"] } + throughput = 600 +} + +`, testAccAzureRMCosmosDbSqlDatabase_basic(rInt, location), rInt) +} + +func testAccAzureRMCosmosDbSqlContainer_update(rInt int, location string) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_cosmosdb_sql_container" "test" { + name = "acctest-CSQLC-%[2]d" + resource_group_name = "${azurerm_cosmosdb_account.test.resource_group_name}" + account_name = "${azurerm_cosmosdb_account.test.name}" + database_name = "${azurerm_cosmosdb_sql_database.test.name}" + partition_key_path = "/definition/id" + unique_key { + paths = ["/definition/id1", "/definition/id2"] + } + throughput = 400 } `, testAccAzureRMCosmosDbSqlDatabase_basic(rInt, location), rInt) diff --git a/azurerm/resource_arm_cosmosdb_sql_database.go b/azurerm/resource_arm_cosmosdb_sql_database.go index ff16a33ba405..0a9670ff3711 100644 --- a/azurerm/resource_arm_cosmosdb_sql_database.go +++ b/azurerm/resource_arm_cosmosdb_sql_database.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "strconv" "time" "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb" @@ -20,6 +21,7 @@ func resourceArmCosmosDbSQLDatabase() *schema.Resource { return &schema.Resource{ Create: resourceArmCosmosDbSQLDatabaseCreate, Read: resourceArmCosmosDbSQLDatabaseRead, + Update: resourceArmCosmosDbSQLDatabaseUpdate, Delete: resourceArmCosmosDbSQLDatabaseDelete, Importer: &schema.ResourceImporter{ @@ -49,6 +51,13 @@ func resourceArmCosmosDbSQLDatabase() *schema.Resource { ForceNew: true, ValidateFunc: validate.CosmosAccountName, }, + + "throughput": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validate.CosmosThroughput, + }, }, } } @@ -62,7 +71,7 @@ func resourceArmCosmosDbSQLDatabaseCreate(d *schema.ResourceData, meta interface resourceGroup := d.Get("resource_group_name").(string) account := d.Get("account_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if features.ShouldResourcesBeImported() { existing, err := client.GetSQLDatabase(ctx, resourceGroup, account, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -87,6 +96,12 @@ func resourceArmCosmosDbSQLDatabaseCreate(d *schema.ResourceData, meta interface }, } + if throughput, hasThroughput := d.GetOk("throughput"); hasThroughput { + db.SQLDatabaseCreateUpdateProperties.Options = map[string]*string{ + "throughput": utils.String(strconv.Itoa(throughput.(int))), + } + } + future, err := client.CreateUpdateSQLDatabase(ctx, resourceGroup, account, name, db) if err != nil { return fmt.Errorf("Error issuing create/update request for Cosmos SQL Database %s (Account %s): %+v", name, account, err) @@ -110,6 +125,59 @@ func resourceArmCosmosDbSQLDatabaseCreate(d *schema.ResourceData, meta interface return resourceArmCosmosDbSQLDatabaseRead(d, meta) } +func resourceArmCosmosDbSQLDatabaseUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Cosmos.DatabaseClient + ctx, cancel := timeouts.ForCreate(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseCosmosDatabaseID(d.Id()) + if err != nil { + return err + } + + db := documentdb.SQLDatabaseCreateUpdateParameters{ + SQLDatabaseCreateUpdateProperties: &documentdb.SQLDatabaseCreateUpdateProperties{ + Resource: &documentdb.SQLDatabaseResource{ + ID: &id.Database, + }, + Options: map[string]*string{}, + }, + } + + future, err := client.CreateUpdateSQLDatabase(ctx, id.ResourceGroup, id.Account, id.Database, db) + if err != nil { + return fmt.Errorf("Error issuing create/update request for Cosmos SQL Database %s (Account %s): %+v", id.Database, id.Account, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on create/update future for Cosmos SQL Database %s (Account %s): %+v", id.Database, id.Account, err) + } + + if d.HasChange("throughput") { + throughputParameters := documentdb.ThroughputUpdateParameters{ + ThroughputUpdateProperties: &documentdb.ThroughputUpdateProperties{ + Resource: &documentdb.ThroughputResource{ + Throughput: utils.Int32(int32(d.Get("throughput").(int))), + }, + }, + } + + throughputFuture, err := client.UpdateSQLDatabaseThroughput(ctx, id.ResourceGroup, id.Account, id.Database, throughputParameters) + if err != nil { + if response.WasNotFound(throughputFuture.Response()) { + return fmt.Errorf("Error setting Throughput for Cosmos SQL Database %s (Account %s) %+v - "+ + "If the collection has not been created with an initial throughput, you cannot configure it later.", id.Database, id.Account, err) + } + } + + if err = throughputFuture.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on ThroughputUpdate future for Cosmos SQL Database %s (Account %s): %+v", id.Database, id.Account, err) + } + } + + return resourceArmCosmosDbSQLDatabaseRead(d, meta) +} + func resourceArmCosmosDbSQLDatabaseRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Cosmos.DatabaseClient ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) @@ -137,6 +205,17 @@ func resourceArmCosmosDbSQLDatabaseRead(d *schema.ResourceData, meta interface{} d.Set("name", props.ID) } + throughputResp, err := client.GetSQLDatabaseThroughput(ctx, id.ResourceGroup, id.Account, id.Database) + if err != nil { + if !utils.ResponseWasNotFound(throughputResp.Response) { + return fmt.Errorf("Error reading Throughput on Cosmos SQL Database '%s' (Account %s) ID: %v", id.Database, id.Account, err) + } else { + d.Set("throughput", nil) + } + } else { + d.Set("throughput", throughputResp.Throughput) + } + return nil } diff --git a/azurerm/resource_arm_cosmosdb_sql_database_test.go b/azurerm/resource_arm_cosmosdb_sql_database_test.go index ace09faa6a46..5770db989d79 100644 --- a/azurerm/resource_arm_cosmosdb_sql_database_test.go +++ b/azurerm/resource_arm_cosmosdb_sql_database_test.go @@ -36,6 +36,45 @@ func TestAccAzureRMCosmosDbSqlDatabase_basic(t *testing.T) { }) } +func TestAccAzureRMCosmosDbSqlDatabase_update(t *testing.T) { + ri := tf.AccRandTimeInt() + resourceName := "azurerm_cosmosdb_sql_database.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMCosmosDbSqlDatabaseDestroy, + Steps: []resource.TestStep{ + { + + Config: testAccAzureRMCosmosDbSqlDatabase_throughput(ri, testLocation(), 700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbSqlDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + + Config: testAccAzureRMCosmosDbSqlDatabase_throughput(ri, testLocation(), 1700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbSqlDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "1700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMCosmosDbSqlDatabaseDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*ArmClient).Cosmos.DatabaseClient ctx := testAccProvider.Meta().(*ArmClient).StopContext @@ -103,3 +142,16 @@ resource "azurerm_cosmosdb_sql_database" "test" { } `, testAccAzureRMCosmosDBAccount_basic(rInt, location, string(documentdb.Eventual), "", ""), rInt) } + +func testAccAzureRMCosmosDbSqlDatabase_throughput(rInt int, location string, throughput int) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_cosmosdb_sql_database" "test" { + name = "acctest-%[2]d" + resource_group_name = "${azurerm_cosmosdb_account.test.resource_group_name}" + account_name = "${azurerm_cosmosdb_account.test.name}" + throughput = %[3]d +} +`, testAccAzureRMCosmosDBAccount_basic(rInt, location, string(documentdb.Eventual), "", ""), rInt, throughput) +} diff --git a/azurerm/resource_arm_cosmosdb_table.go b/azurerm/resource_arm_cosmosdb_table.go index 4c847851d428..0d95aaffc86e 100644 --- a/azurerm/resource_arm_cosmosdb_table.go +++ b/azurerm/resource_arm_cosmosdb_table.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "strconv" "time" "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb" @@ -20,6 +21,7 @@ func resourceArmCosmosDbTable() *schema.Resource { return &schema.Resource{ Create: resourceArmCosmosDbTableCreate, Read: resourceArmCosmosDbTableRead, + Update: resourceArmCosmosDbTableUpdate, Delete: resourceArmCosmosDbTableDelete, Importer: &schema.ResourceImporter{ @@ -49,6 +51,13 @@ func resourceArmCosmosDbTable() *schema.Resource { ForceNew: true, ValidateFunc: validate.CosmosAccountName, }, + + "throughput": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validate.CosmosThroughput, + }, }, } } @@ -62,7 +71,7 @@ func resourceArmCosmosDbTableCreate(d *schema.ResourceData, meta interface{}) er resourceGroup := d.Get("resource_group_name").(string) account := d.Get("account_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if features.ShouldResourcesBeImported() { existing, err := client.GetTable(ctx, resourceGroup, account, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -87,6 +96,12 @@ func resourceArmCosmosDbTableCreate(d *schema.ResourceData, meta interface{}) er }, } + if throughput, hasThroughput := d.GetOk("throughput"); hasThroughput { + db.TableCreateUpdateProperties.Options = map[string]*string{ + "throughput": utils.String(strconv.Itoa(throughput.(int))), + } + } + future, err := client.CreateUpdateTable(ctx, resourceGroup, account, name, db) if err != nil { return fmt.Errorf("Error issuing create/update request for Cosmos Table %s (Account %s): %+v", name, account, err) @@ -110,6 +125,59 @@ func resourceArmCosmosDbTableCreate(d *schema.ResourceData, meta interface{}) er return resourceArmCosmosDbTableRead(d, meta) } +func resourceArmCosmosDbTableUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Cosmos.DatabaseClient + ctx, cancel := timeouts.ForCreate(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseCosmosTableID(d.Id()) + if err != nil { + return err + } + + db := documentdb.TableCreateUpdateParameters{ + TableCreateUpdateProperties: &documentdb.TableCreateUpdateProperties{ + Resource: &documentdb.TableResource{ + ID: &id.Table, + }, + Options: map[string]*string{}, + }, + } + + future, err := client.CreateUpdateTable(ctx, id.ResourceGroup, id.Account, id.Table, db) + if err != nil { + return fmt.Errorf("Error issuing create/update request for Cosmos Table %s (Account %s): %+v", id.Table, id.Account, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on create/update future for Cosmos Table %s (Account %s): %+v", id.Table, id.Account, err) + } + + if d.HasChange("throughput") { + throughputParameters := documentdb.ThroughputUpdateParameters{ + ThroughputUpdateProperties: &documentdb.ThroughputUpdateProperties{ + Resource: &documentdb.ThroughputResource{ + Throughput: utils.Int32(int32(d.Get("throughput").(int))), + }, + }, + } + + throughputFuture, err := client.UpdateTableThroughput(ctx, id.ResourceGroup, id.Account, id.Table, throughputParameters) + if err != nil { + if response.WasNotFound(throughputFuture.Response()) { + return fmt.Errorf("Error setting Throughput for Cosmos Table %s (Account %s): %+v - "+ + "If the collection has not been created with an initial throughput, you cannot configure it later.", id.Table, id.Account, err) + } + } + + if err = throughputFuture.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting on ThroughputUpdate future for Cosmos Table %s (Account %s): %+v", id.Table, id.Account, err) + } + } + + return resourceArmCosmosDbTableRead(d, meta) +} + func resourceArmCosmosDbTableRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Cosmos.DatabaseClient ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) @@ -137,6 +205,17 @@ func resourceArmCosmosDbTableRead(d *schema.ResourceData, meta interface{}) erro d.Set("name", props.ID) } + throughputResp, err := client.GetTableThroughput(ctx, id.ResourceGroup, id.Account, id.Table) + if err != nil { + if !utils.ResponseWasNotFound(throughputResp.Response) { + return fmt.Errorf("Error reading Throughput on Cosmos Table %s (Account %s) ID: %v", id.Table, id.Account, err) + } else { + d.Set("throughput", nil) + } + } else { + d.Set("throughput", throughputResp.Throughput) + } + return nil } diff --git a/azurerm/resource_arm_cosmosdb_table_test.go b/azurerm/resource_arm_cosmosdb_table_test.go index d41e2dcf5293..26257e7b6f4a 100644 --- a/azurerm/resource_arm_cosmosdb_table_test.go +++ b/azurerm/resource_arm_cosmosdb_table_test.go @@ -35,6 +35,45 @@ func TestAccAzureRMCosmosDbTable_basic(t *testing.T) { }) } +func TestAccAzureRMCosmosDbTable_update(t *testing.T) { + ri := tf.AccRandTimeInt() + resourceName := "azurerm_cosmosdb_table.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMCosmosDbTableDestroy, + Steps: []resource.TestStep{ + { + + Config: testAccAzureRMCosmosDbTable_throughput(ri, testLocation(), 700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbTableExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + + Config: testAccAzureRMCosmosDbTable_throughput(ri, testLocation(), 1700), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMCosmosDbTableExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "throughput", "1700"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMCosmosDbTableDestroy(s *terraform.State) error { client := testAccProvider.Meta().(*ArmClient).Cosmos.DatabaseClient ctx := testAccProvider.Meta().(*ArmClient).StopContext @@ -102,3 +141,16 @@ resource "azurerm_cosmosdb_table" "test" { } `, testAccAzureRMCosmosDBAccount_capabilityTable(rInt, location), rInt) } + +func testAccAzureRMCosmosDbTable_throughput(rInt int, location string, throughput int) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_cosmosdb_table" "test" { + name = "acctest-%[2]d" + resource_group_name = "${azurerm_cosmosdb_account.test.resource_group_name}" + account_name = "${azurerm_cosmosdb_account.test.name}" + throughput = %[3]d +} +`, testAccAzureRMCosmosDBAccount_capabilityTable(rInt, location), rInt, throughput) +} diff --git a/website/docs/r/cosmosdb_cassandra_keyspace.html.markdown b/website/docs/r/cosmosdb_cassandra_keyspace.html.markdown index 51870a331557..10e85f6aede2 100644 --- a/website/docs/r/cosmosdb_cassandra_keyspace.html.markdown +++ b/website/docs/r/cosmosdb_cassandra_keyspace.html.markdown @@ -42,6 +42,7 @@ resource "azurerm_cosmosdb_cassandra_keyspace" "example" { name = "tfex-cosmos-cassandra-keyspace" resource_group_name = data.azurerm_cosmosdb_account.example.resource_group_name account_name = azurerm_cosmosdb_account.example.name + throughput = 400 } ``` @@ -55,6 +56,8 @@ The following arguments are supported: * `account_name` - (Required) The name of the Cosmos DB Cassandra KeySpace to create the table within. Changing this forces a new resource to be created. +* `throughput` - (Optional) The throughput of Cassandra keyspace (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. + ## Attributes Reference diff --git a/website/docs/r/cosmosdb_sql_container.html.markdown b/website/docs/r/cosmosdb_sql_container.html.markdown index ead8940151ca..3c788fe3a8cc 100644 --- a/website/docs/r/cosmosdb_sql_container.html.markdown +++ b/website/docs/r/cosmosdb_sql_container.html.markdown @@ -21,7 +21,8 @@ resource "azurerm_cosmosdb_sql_container" "example" { account_name = "${azurerm_cosmosdb_account.example.name}" database_name = "${azurerm_cosmosdb_sql_database.example.name}" partition_key_path = "/definition/id" - + throughput = 400 + unique_key { paths = ["/definition/idlong", "/definition/idshort"] } @@ -45,6 +46,8 @@ The following arguments are supported: * `unique_key` - (Optional) One or more `unique_key` blocks as defined below. Changing this forces a new resource to be created. +* `throughput` - (Optional) The throughput of SQL container (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. + --- A `unique_key` block supports the following: diff --git a/website/docs/r/cosmosdb_sql_database.html.markdown b/website/docs/r/cosmosdb_sql_database.html.markdown index a641e4e4ddd5..7b3a0f6c5ec2 100644 --- a/website/docs/r/cosmosdb_sql_database.html.markdown +++ b/website/docs/r/cosmosdb_sql_database.html.markdown @@ -23,6 +23,7 @@ resource "azurerm_cosmosdb_sql_database" "example" { name = "tfex-cosmos-mongo-db" resource_group_name = "${data.azurerm_cosmosdb_account.example.resource_group_name}" account_name = "${data.azurerm_cosmosdb_account.example.name}" + throughput = 400 } ``` @@ -36,6 +37,8 @@ The following arguments are supported: * `account_name` - (Required) The name of the Cosmos DB SQL Database to create the table within. Changing this forces a new resource to be created. +* `throughput` - (Optional) The throughput of SQL database (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. + ## Attributes Reference diff --git a/website/docs/r/cosmosdb_table.html.markdown b/website/docs/r/cosmosdb_table.html.markdown index e34848da1ed8..e9734f3922f3 100644 --- a/website/docs/r/cosmosdb_table.html.markdown +++ b/website/docs/r/cosmosdb_table.html.markdown @@ -23,6 +23,7 @@ resource "azurerm_cosmosdb_table" "example" { name = "tfex-cosmos-table" resource_group_name = "${data.azurerm_cosmosdb_account.example.resource_group_name}" account_name = "${data.azurerm_cosmosdb_account.example.name}" + throughput = 400 } ``` @@ -36,6 +37,8 @@ The following arguments are supported: * `account_name` - (Required) The name of the Cosmos DB Table to create the table within. Changing this forces a new resource to be created. +* `throughput` - (Optional) The throughput of Table (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. + ## Attributes Reference