Skip to content

Commit

Permalink
[Bug Fix] Fixes PostgreSQL collation issues #396 and #760 (#1255)
Browse files Browse the repository at this point in the history
* Update PostgreSQL to GA 2017-12-01 API

* Added TestCheckResourceAttr for create_mode to tests

* Upgraded Go SDK to v16.2.1 to match Master Branch

* Replaced 2017-04-30-preview postgreSQL API  with 2017-12-01 GA API

* Removed CreateMode from schema, updated tests and documentation to match

* Removed createmode validation from tests

* Removed createmode from two hcl sections

* [Bug Fix] Fixes issues #396 and #760

* Updated validators to match master branch

* Fixing a merge conflict

* Removed debug fmt statement

* Removed AzureRMNormalizeCollation util function

* Updated replace methiod

* Updated validator to use regex instead of string contains

* Made charset case insensitive and added two test cases

* Switching to use the fields within `.Properties` to match the API

Also working around a potential crash. Tests pass:

```
$ acctests azurerm TestAccAzureRMPostgreSQLDatabase_
=== RUN   TestAccAzureRMPostgreSQLDatabase_importBasic
--- PASS: TestAccAzureRMPostgreSQLDatabase_importBasic (402.40s)
=== RUN   TestAccAzureRMPostgreSQLDatabase_basic
--- PASS: TestAccAzureRMPostgreSQLDatabase_basic (486.39s)
=== RUN   TestAccAzureRMPostgreSQLDatabase_charsetLowercase
--- PASS: TestAccAzureRMPostgreSQLDatabase_charsetLowercase (424.71s)
=== RUN   TestAccAzureRMPostgreSQLDatabase_charsetMixedcase
--- PASS: TestAccAzureRMPostgreSQLDatabase_charsetMixedcase (424.97s)
PASS
ok  	github.com/terraform-providers/terraform-provider-azurerm/azurerm	1738.507s
```
WodansSon authored and tombuildsstuff committed May 24, 2018
1 parent b841fdf commit 6070152
Showing 5 changed files with 195 additions and 10 deletions.
26 changes: 18 additions & 8 deletions azurerm/resource_arm_postgresql_database.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package azurerm
import (
"fmt"
"log"
"strings"

"github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql"
"github.com/hashicorp/terraform/helper/schema"
@@ -35,15 +36,17 @@ func resourceArmPostgreSQLDatabase() *schema.Resource {
},

"charset": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ForceNew: true,
},

"collation": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateCollation(),
},
},
}
@@ -118,8 +121,15 @@ func resourceArmPostgreSQLDatabaseRead(d *schema.ResourceData, meta interface{})
d.Set("name", resp.Name)
d.Set("resource_group_name", resGroup)
d.Set("server_name", serverName)
d.Set("charset", resp.Charset)
d.Set("collation", resp.Collation)

if props := resp.DatabaseProperties; props != nil {
d.Set("charset", props.Charset)

if collation := props.Collation; collation != nil {
v := strings.Replace(*collation, "-", "_", -1)
d.Set("collation", v)
}
}

return nil
}
125 changes: 125 additions & 0 deletions azurerm/resource_arm_postgresql_database_test.go
Original file line number Diff line number Diff line change
@@ -24,7 +24,50 @@ func TestAccAzureRMPostgreSQLDatabase_basic(t *testing.T) {
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMPostgreSQLDatabaseExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "charset", "UTF8"),
resource.TestCheckResourceAttr(resourceName, "collation", "English_United States.1252"),
),
},
},
})
}

func TestAccAzureRMPostgreSQLDatabase_charsetLowercase(t *testing.T) {
resourceName := "azurerm_postgresql_database.test"
ri := acctest.RandInt()
config := testAccAzureRMPostgreSQLDatabase_charsetLowercase(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPostgreSQLDatabaseDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMPostgreSQLDatabaseExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "charset", "UTF8"),
resource.TestCheckResourceAttr(resourceName, "collation", "English_United States.1252"),
),
},
},
})
}

func TestAccAzureRMPostgreSQLDatabase_charsetMixedcase(t *testing.T) {
resourceName := "azurerm_postgresql_database.test"
ri := acctest.RandInt()
config := testAccAzureRMPostgreSQLDatabase_charsetMixedcase(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPostgreSQLDatabaseDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMPostgreSQLDatabaseExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "charset", "UTF8"),
resource.TestCheckResourceAttr(resourceName, "collation", "English_United States.1252"),
),
@@ -132,3 +175,85 @@ resource "azurerm_postgresql_database" "test" {
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMPostgreSQLDatabase_charsetLowercase(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_postgresql_server" "test" {
name = "acctestpsqlsvr-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku {
name = "B_Gen4_2"
capacity = 2
tier = "Basic"
family = "Gen4"
}
storage_profile {
storage_mb = 51200
backup_retention_days = 7
geo_redundant_backup = "Disabled"
}
administrator_login = "acctestun"
administrator_login_password = "H@Sh1CoR3!"
version = "9.6"
ssl_enforcement = "Enabled"
}
resource "azurerm_postgresql_database" "test" {
name = "acctestdb_%d"
resource_group_name = "${azurerm_resource_group.test.name}"
server_name = "${azurerm_postgresql_server.test.name}"
charset = "utf8"
collation = "English_United States.1252"
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMPostgreSQLDatabase_charsetMixedcase(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_postgresql_server" "test" {
name = "acctestpsqlsvr-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku {
name = "B_Gen4_2"
capacity = 2
tier = "Basic"
family = "Gen4"
}
storage_profile {
storage_mb = 51200
backup_retention_days = 7
geo_redundant_backup = "Disabled"
}
administrator_login = "acctestun"
administrator_login_password = "H@Sh1CoR3!"
version = "9.6"
ssl_enforcement = "Enabled"
}
resource "azurerm_postgresql_database" "test" {
name = "acctestdb_%d"
resource_group_name = "${azurerm_resource_group.test.name}"
server_name = "${azurerm_postgresql_server.test.name}"
charset = "Utf8"
collation = "English_United States.1252"
}
`, rInt, location, rInt, rInt)
}
19 changes: 19 additions & 0 deletions azurerm/validators.go
Original file line number Diff line number Diff line change
@@ -99,3 +99,22 @@ func validateIntBetweenDivisibleBy(min, max, divisor int) schema.SchemaValidateF
return
}
}

func validateCollation() schema.SchemaValidateFunc {
return func(i interface{}, k string) (s []string, es []error) {
v, ok := i.(string)
if !ok {
es = append(es, fmt.Errorf("expected type of %s to be string", k))
return
}

matched, _ := regexp.MatchString(`^[A-Za-z0-9_. ]+$`, v)

if !matched {
es = append(es, fmt.Errorf("%s contains invalid characters, only underscores are supported, got %s", k, v))
return
}

return
}
}
33 changes: 32 additions & 1 deletion azurerm/validators_test.go
Original file line number Diff line number Diff line change
@@ -178,7 +178,38 @@ func TestValidateIntBetweenDivisibleBy(t *testing.T) {
for _, tc := range cases {
_, errors := validateIntBetweenDivisibleBy(tc.Min, tc.Max, tc.Div)(tc.Value, strconv.Itoa(tc.Value.(int)))
if len(errors) != tc.Errors {
t.Fatalf("Expected intBetweenDivisibleBy to trigger '%d' errors for '%s' - got '%d' ['%s']", tc.Errors, tc.Value, len(errors), errors[0])
t.Fatalf("Expected intBetweenDivisibleBy to trigger '%d' errors for '%s' - got '%d'", tc.Errors, tc.Value, len(errors))
}
}
}

func TestValidateCollation(t *testing.T) {
cases := []struct {
Value string
Errors int
}{
{
Value: "en-US",
Errors: 1,
},
{
Value: "en_US",
Errors: 0,
},
{
Value: "en US",
Errors: 0,
},
{
Value: "English_United States.1252",
Errors: 0,
},
}

for _, tc := range cases {
_, errors := validateCollation()(tc.Value, "collation")
if len(errors) != tc.Errors {
t.Fatalf("Expected validateCollation to trigger '%d' errors for '%s' - got '%d'", tc.Errors, tc.Value, len(errors))
}
}
}
2 changes: 1 addition & 1 deletion website/docs/r/postgresql_server.html.markdown
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ The following arguments are supported:
`sku` supports the following:

* `name` - (Required) Specifies the SKU Name for this PostgreSQL Server. The name of the SKU, follows the `tier` + `family` + `cores` pattern (e.g. B_Gen4_1, GP_Gen5_8). For more information see the [product documentation](https://docs.microsoft.com/en-us/rest/api/postgresql/servers/create#sku).

* `capacity` - (Required) The scale up/out capacity, representing server's compute units.

* `tier` - (Required) The tier of the particular SKU. Possible values are `Basic`, `GeneralPurpose`, and `MemoryOptimized`. For more information see the [product documentation](https://docs.microsoft.com/en-us/azure/postgresql/concepts-pricing-tiers).

0 comments on commit 6070152

Please sign in to comment.