Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_cosmos_mongo_*: fix throughput & deprecate indexes #5116

Merged
merged 12 commits into from
Dec 11, 2019
117 changes: 88 additions & 29 deletions azurerm/resource_arm_cosmosdb_mongo_collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package azurerm
import (
"fmt"
"log"
"net/http"
"strconv"
"strings"
"time"

Expand All @@ -20,9 +22,9 @@ import (

func resourceArmCosmosDbMongoCollection() *schema.Resource {
return &schema.Resource{
Create: resourceArmCosmosDbMongoCollectionCreateUpdate,
Create: resourceArmCosmosDbMongoCollectionCreate,
Read: resourceArmCosmosDbMongoCollectionRead,
Update: resourceArmCosmosDbMongoCollectionCreateUpdate,
Update: resourceArmCosmosDbMongoCollectionUpdate,
Delete: resourceArmCosmosDbMongoCollectionDelete,

Importer: &schema.ResourceImporter{
Expand Down Expand Up @@ -78,13 +80,14 @@ func resourceArmCosmosDbMongoCollection() *schema.Resource {
"throughput": {
Type: schema.TypeInt,
Optional: true,
Default: 400,
Computed: true,
ValidateFunc: validate.CosmosThroughput,
},

"indexes": {
Type: schema.TypeSet,
Optional: true,
Type: schema.TypeSet,
Optional: true,
Deprecated: "Indexes are ignored unless they are the shared key so have ben deprecated. ",
katbyte marked this conversation as resolved.
Show resolved Hide resolved
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Expand All @@ -108,7 +111,7 @@ func resourceArmCosmosDbMongoCollection() *schema.Resource {
}
}

func resourceArmCosmosDbMongoCollectionCreateUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceArmCosmosDbMongoCollectionCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).Cosmos.DatabaseClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d)
defer cancel()
Expand All @@ -117,9 +120,8 @@ func resourceArmCosmosDbMongoCollectionCreateUpdate(d *schema.ResourceData, meta
resourceGroup := d.Get("resource_group_name").(string)
account := d.Get("account_name").(string)
database := d.Get("database_name").(string)
throughput := d.Get("throughput").(int)

if features.ShouldResourcesBeImported() && d.IsNewResource() {
if features.ShouldResourcesBeImported() {
existing, err := client.GetMongoDBCollection(ctx, resourceGroup, account, database, name)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
Expand Down Expand Up @@ -150,6 +152,12 @@ func resourceArmCosmosDbMongoCollectionCreateUpdate(d *schema.ResourceData, meta
},
}

if throughput, hasThroughput := d.GetOk("throughput"); hasThroughput {
db.MongoDBCollectionCreateUpdateProperties.Options = map[string]*string{
"throughput": utils.String(strconv.Itoa(throughput.(int))),
}
}

if v, ok := d.GetOkExists("shard_key"); ok {
db.MongoDBCollectionCreateUpdateProperties.Resource.ShardKey = map[string]*string{
v.(string): utils.String("Hash"), // looks like only hash is supported for now
Expand All @@ -165,33 +173,82 @@ func resourceArmCosmosDbMongoCollectionCreateUpdate(d *schema.ResourceData, meta
return fmt.Errorf("Error waiting on create/update future for Cosmos Mongo Collection %s (Account %s, Database %s): %+v", name, account, database, err)
}

throughputParameters := documentdb.ThroughputUpdateParameters{
ThroughputUpdateProperties: &documentdb.ThroughputUpdateProperties{
Resource: &documentdb.ThroughputResource{
Throughput: utils.Int32(int32(throughput)),
},
},
resp, err := client.GetMongoDBCollection(ctx, resourceGroup, account, database, name)
if err != nil {
return fmt.Errorf("Error making get request for Cosmos Mongo Collection %s (Account %s, Database %s): %+v", name, account, database, err)
}

throughputFuture, err := client.UpdateMongoDBCollectionThroughput(ctx, resourceGroup, account, database, name, throughputParameters)
id, err := azure.CosmosGetIDFromResponse(resp.Response)
if err != nil {
return fmt.Errorf("Error setting Throughput for Cosmos MongoDB Collection %s (Account %s, Database %s): %+v", name, account, database, err)
return fmt.Errorf("Error getting ID for Cosmos Mongo Collection %s (Account %s, Database %s) ID: %v", name, account, database, err)
}
d.SetId(id)

if err = throughputFuture.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("Error waiting on ThroughputUpdate future for Cosmos Mongo Collection %s (Account %s, Database %s): %+v", name, account, database, err)
}
return resourceArmCosmosDbMongoCollectionRead(d, meta)
}

resp, err := client.GetMongoDBCollection(ctx, resourceGroup, account, database, name)
func resourceArmCosmosDbMongoCollectionUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).Cosmos.DatabaseClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d)
defer cancel()

id, err := azure.ParseCosmosDatabaseCollectionID(d.Id())
if err != nil {
return fmt.Errorf("Error making get request for Cosmos Mongo Collection %s (Account %s, Database %s): %+v", name, account, database, err)
return err
}

id, err := azure.CosmosGetIDFromResponse(resp.Response)
var ttl *int
if v, ok := d.GetOkExists("default_ttl_seconds"); ok {
ttl = utils.Int(v.(int))
}

db := documentdb.MongoDBCollectionCreateUpdateParameters{
MongoDBCollectionCreateUpdateProperties: &documentdb.MongoDBCollectionCreateUpdateProperties{
Resource: &documentdb.MongoDBCollectionResource{
ID: &id.Collection,
Indexes: expandCosmosMongoCollectionIndexes(d.Get("indexes"), ttl),
},
Options: map[string]*string{},
},
}

if v, ok := d.GetOkExists("shard_key"); ok {
db.MongoDBCollectionCreateUpdateProperties.Resource.ShardKey = map[string]*string{
v.(string): utils.String("Hash"), // looks like only hash is supported for now
}
}

future, err := client.CreateUpdateMongoDBCollection(ctx, id.ResourceGroup, id.Account, id.Database, id.Collection, db)
if err != nil {
return fmt.Errorf("Error getting ID for Cosmos Mongo Collection %s (Account %s, Database %s) ID: %v", name, account, database, err)
return fmt.Errorf("Error issuing create/update request for Cosmos Mongo Collection %s (Account %s, Database %s): %+v", id.Collection, 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 Mongo Collection %s (Account %s, Database %s): %+v", id.Collection, 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.UpdateMongoDBCollectionThroughput(ctx, id.ResourceGroup, id.Account, id.Database, id.Collection, throughputParameters)
if err != nil {
if throughputFuture.Response().StatusCode == http.StatusNotFound {
d.Set("throughput", nil)
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)
}
}

if err = throughputFuture.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("Error waiting on ThroughputUpdate future for Cosmos Mongo Collection %s (Account %s, Database %s): %+v", id.Collection, id.Account, id.Database, err)
}
}
d.SetId(id)

return resourceArmCosmosDbMongoCollectionRead(d, meta)
}
Expand Down Expand Up @@ -243,11 +300,13 @@ func resourceArmCosmosDbMongoCollectionRead(d *schema.ResourceData, meta interfa

throughputResp, err := client.GetMongoDBCollectionThroughput(ctx, id.ResourceGroup, id.Account, id.Database, id.Collection)
if err != nil {
return fmt.Errorf("Error reading Throughput on Cosmos Mongo Collection %s (Account %s, Database %s): %+v", id.Collection, id.Account, id.Database, err)
}

if throughput := throughputResp.Throughput; throughput != nil {
d.Set("throughput", int(*throughput))
if !utils.ResponseWasNotFound(throughputResp.Response) {
return fmt.Errorf("Error reading Throughput on Cosmos Mongo Collection %s (Account %s, Database %s): %+v", id.Collection, id.Account, id.Database, err)
} else {
d.Set("throughput", nil)
}
} else {
d.Set("throughput", throughputResp.Throughput)
}

return nil
Expand Down
102 changes: 66 additions & 36 deletions azurerm/resource_arm_cosmosdb_mongo_collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func TestAccAzureRMCosmosDbMongoCollection_basic(t *testing.T) {
Config: testAccAzureRMCosmosDbMongoCollection_basic(ri, testLocation()),
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "throughput", "400"),
),
},
{
Expand All @@ -48,10 +49,8 @@ func TestAccAzureRMCosmosDbMongoCollection_complete(t *testing.T) {
Config: testAccAzureRMCosmosDbMongoCollection_complete(ri, testLocation()),
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "shard_key", "day"),
resource.TestCheckResourceAttr(resourceName, "shard_key", "seven"),
resource.TestCheckResourceAttr(resourceName, "default_ttl_seconds", "707"),
resource.TestCheckResourceAttr(resourceName, "indexes.#", "2"),
resource.TestCheckResourceAttr(resourceName, "throughput", "600"),
),
},
{
Expand Down Expand Up @@ -82,10 +81,8 @@ func TestAccAzureRMCosmosDbMongoCollection_update(t *testing.T) {
Config: testAccAzureRMCosmosDbMongoCollection_complete(ri, testLocation()),
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "shard_key", "day"),
resource.TestCheckResourceAttr(resourceName, "shard_key", "seven"),
resource.TestCheckResourceAttr(resourceName, "default_ttl_seconds", "707"),
resource.TestCheckResourceAttr(resourceName, "indexes.#", "2"),
resource.TestCheckResourceAttr(resourceName, "throughput", "600"),
),
},
{
Expand All @@ -98,8 +95,52 @@ func TestAccAzureRMCosmosDbMongoCollection_update(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "default_ttl_seconds", "70707"),
resource.TestCheckResourceAttr(resourceName, "indexes.#", "3"),
resource.TestCheckResourceAttr(resourceName, "throughput", "400"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMCosmosDbMongoCollection_throughput(t *testing.T) {
ri := tf.AccRandTimeInt()
resourceName := "azurerm_cosmosdb_mongo_collection.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMCosmosDbMongoCollectionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMCosmosDbMongoCollection_throughput(ri, testLocation(), 700),
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAzureRMCosmosDbMongoCollection_throughput(ri, testLocation(), 1400),
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAzureRMCosmosDbMongoCollection_basic(ri, testLocation()),
Check: resource.ComposeAggregateTestCheckFunc(
testCheckAzureRMCosmosDbMongoCollectionExists(resourceName),
),
},
{
Expand Down Expand Up @@ -192,19 +233,8 @@ resource "azurerm_cosmosdb_mongo_collection" "test" {
account_name = "${azurerm_cosmosdb_mongo_database.test.account_name}"
database_name = "${azurerm_cosmosdb_mongo_database.test.name}"

shard_key = "seven"
default_ttl_seconds = 707
shard_key = "day"
throughput = 600

indexes {
key = "seven"
unique = false
}

indexes {
key = "day"
unique = true
}
}
`, testAccAzureRMCosmosDbMongoDatabase_basic(rInt, location), rInt)
}
Expand All @@ -219,23 +249,23 @@ resource "azurerm_cosmosdb_mongo_collection" "test" {
account_name = "${azurerm_cosmosdb_mongo_database.test.account_name}"
database_name = "${azurerm_cosmosdb_mongo_database.test.name}"

shard_key = "seven"
default_ttl_seconds = 70707
throughput = 400

indexes {
key = "seven"
unique = true
}

indexes {
key = "day"
unique = false
}

indexes {
key = "fool"
unique = false
}
}
`, testAccAzureRMCosmosDbMongoDatabase_basic(rInt, location), rInt)
}

func testAccAzureRMCosmosDbMongoCollection_throughput(rInt int, location string, throughput int) string {
return fmt.Sprintf(`
%[1]s

resource "azurerm_cosmosdb_mongo_collection" "test" {
name = "acctest-%[2]d"
resource_group_name = "${azurerm_cosmosdb_mongo_database.test.resource_group_name}"
account_name = "${azurerm_cosmosdb_mongo_database.test.account_name}"
database_name = "${azurerm_cosmosdb_mongo_database.test.name}"

throughput = %[3]d
}
`, testAccAzureRMCosmosDbMongoDatabase_basic(rInt, location), rInt, throughput)
}
Loading