Skip to content

Commit

Permalink
Including #24892
Browse files Browse the repository at this point in the history
* Initial Check-in...

* Fix typo in update function...

* Add note to documentation for the new storage_tier field...

* Check-in progress...

* Fix lint error...

* Adding test cases...

* Update mapping table...

* Remove comments...

* Fix test validation...

* Reduce size of upscale...

* Added 4193280 back in as a valid value for storage_mb...

* Update document table...

* Add host caching note to table...

* Move default value assignment from diff to expand...

* Move logic back to custom diff...

* Add code to make defaults work in create...

* Move default values from expand into create only...

* Update code comment...

* Fix for gradually deprecated functions...
  • Loading branch information
WodansSon authored Feb 22, 2024
1 parent d89a40b commit 3721fe5
Show file tree
Hide file tree
Showing 4 changed files with 384 additions and 11 deletions.
112 changes: 106 additions & 6 deletions internal/services/postgres/postgresql_flexible_server_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/postgresql/2021-06-01/serverrestart"
"github.com/hashicorp/go-azure-sdk/resource-manager/postgresql/2023-06-01-preview/servers"
"github.com/hashicorp/go-azure-sdk/resource-manager/privatedns/2020-06-01/privatezones"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate"
Expand Down Expand Up @@ -133,6 +134,25 @@ func resourcePostgresqlFlexibleServer() *pluginsdk.Resource {
ValidateFunc: validation.IntInSlice([]int{32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4193280, 4194304, 8388608, 16777216, 33553408}),
},

"storage_tier": {
Type: pluginsdk.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{
string(servers.AzureManagedDiskPerformanceTiersPFour),
string(servers.AzureManagedDiskPerformanceTiersPSix),
string(servers.AzureManagedDiskPerformanceTiersPOneZero),
string(servers.AzureManagedDiskPerformanceTiersPOneFive),
string(servers.AzureManagedDiskPerformanceTiersPTwoZero),
string(servers.AzureManagedDiskPerformanceTiersPThreeZero),
string(servers.AzureManagedDiskPerformanceTiersPFourZero),
string(servers.AzureManagedDiskPerformanceTiersPFiveZero),
string(servers.AzureManagedDiskPerformanceTiersPSixZero),
string(servers.AzureManagedDiskPerformanceTiersPSevenZero),
string(servers.AzureManagedDiskPerformanceTiersPEightZero),
}, false),
},

"version": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -344,6 +364,58 @@ func resourcePostgresqlFlexibleServer() *pluginsdk.Resource {
if oldLoginName != "" {
diff.ForceNew("administrator_login")
}
return nil
}, func(ctx context.Context, diff *pluginsdk.ResourceDiff, v interface{}) error {
storageTierMappings := validate.InitializeFlexibleServerStorageTierDefaults()
var newTier string
var newMb int
var isValid bool

oldStorageMbRaw, newStorageMbRaw := diff.GetChange("storage_mb")
oldTierRaw, newTierRaw := diff.GetChange("storage_tier")

if oldStorageMbRaw.(int) == 0 && oldTierRaw.(string) == "" && newStorageMbRaw.(int) == 0 && newTierRaw.(string) == "" {
// This is a new resource without any values in the state
// or config, default values will be set in create...
return nil
}

newMb = newStorageMbRaw.(int)
newTier = newTierRaw.(string)

// storage_mb can only be scaled up...
if newMb < oldStorageMbRaw.(int) {
return fmt.Errorf("'storage_mb' can only be scaled up, expected the new 'storage_mb' value (%d) to be larger than the previous 'storage_mb' value (%d)", newMb, oldStorageMbRaw.(int))
}

// if newMb or newTier values are empty,
// assign the default values that will
// be assigned in the create func...
if newMb == 0 {
newMb = 32768
}

// get the valid mappings for the passed
// storage_mb size...
storageTiers := storageTierMappings[newMb]

if newTier == "" {
newTier = string(storageTiers.DefaultTier)
}

// verify that the storage_tier is valid
// for the given storage_mb...
for _, tier := range *storageTiers.ValidTiers {
if newTier == tier {
isValid = true
break
}
}

if !isValid {
return fmt.Errorf("invalid 'storage_tier' %q for defined 'storage_mb' size '%d', expected one of [%s]", newTier, newMb, azure.QuotedStringSlice(*storageTiers.ValidTiers))
}

return nil
},
),
Expand Down Expand Up @@ -408,6 +480,7 @@ func resourcePostgresqlFlexibleServerCreate(d *pluginsdk.ResourceData, meta inte
if !adminLoginSet {
return fmt.Errorf("`administrator_login` is required when `create_mode` is `Default` and `authentication.password_auth_enabled` is set to `true`")
}

if !adminPwdSet {
return fmt.Errorf("`administrator_password` is required when `create_mode` is `Default` and `authentication.password_auth_enabled` is set to `true`")
}
Expand All @@ -418,24 +491,43 @@ func resourcePostgresqlFlexibleServerCreate(d *pluginsdk.ResourceData, meta inte
if _, ok := d.GetOk("sku_name"); !ok {
return fmt.Errorf("`sku_name` is required when `create_mode` is `Default`")
}

if _, ok := d.GetOk("version"); !ok {
return fmt.Errorf("`version` is required when `create_mode` is `Default`")
}
if _, ok := d.GetOk("storage_mb"); !ok {
return fmt.Errorf("`storage_mb` is required when `create_mode` is `Default`")
}
}

sku, err := expandFlexibleServerSku(d.Get("sku_name").(string))
if err != nil {
return fmt.Errorf("expanding `sku_name` for %s: %v", id, err)
}

storage := expandArmServerStorage(d)
var storageMb int

if storage.StorageSizeGB == nil || *storage.StorageSizeGB == 0 {
// set the default value for storage_mb...
storageMb = 32768
storage.StorageSizeGB = pointer.FromInt64(int64(32))
log.Printf("[DEBUG]: Default 'storage_mb' Set -> %d\n", storageMb)
} else {
storageMb = int(*storage.StorageSizeGB) * 1024
}

if storage.Tier == nil || *storage.Tier == "" {
// determine the correct default storage_tier based
// on the defined storage_mb...
storageTierMappings := validate.InitializeFlexibleServerStorageTierDefaults()
storageTiers := storageTierMappings[storageMb]
storage.Tier = pointer.To(storageTiers.DefaultTier)
log.Printf("[DEBUG]: Default 'storage_tier' Set -> %q\n", storageTiers.DefaultTier)
}

parameters := servers.Server{
Location: location.Normalize(d.Get("location").(string)),
Properties: &servers.ServerProperties{
Network: expandArmServerNetwork(d),
Storage: expandArmServerStorage(d),
Storage: storage,
HighAvailability: expandFlexibleServerHighAvailability(d.Get("high_availability").([]interface{}), true),
Backup: expandArmServerBackup(d),
DataEncryption: expandFlexibleServerDataEncryption(d.Get("customer_managed_key").([]interface{})),
Expand Down Expand Up @@ -573,6 +665,10 @@ func resourcePostgresqlFlexibleServerRead(d *pluginsdk.ResourceData, meta interf
if storage.StorageSizeGB != nil {
d.Set("storage_mb", (*storage.StorageSizeGB * 1024))
}

if storage.Tier != nil {
d.Set("storage_tier", string(*storage.Tier))
}
}

if backup := props.Backup; backup != nil {
Expand Down Expand Up @@ -741,7 +837,7 @@ func resourcePostgresqlFlexibleServerUpdate(d *pluginsdk.ResourceData, meta inte
parameters.Properties.AuthConfig = expandFlexibleServerAuthConfig(d.Get("authentication").([]interface{}))
}

if d.HasChange("auto_grow_enabled") || d.HasChange("storage_mb") {
if d.HasChange("auto_grow_enabled") || d.HasChange("storage_mb") || d.HasChange("storage_tier") {
// TODO remove the additional update after https://github.com/Azure/azure-rest-api-specs/issues/22867 is fixed
storageUpdateParameters := servers.ServerForUpdate{
Properties: &servers.ServerPropertiesForUpdate{
Expand Down Expand Up @@ -898,7 +994,11 @@ func expandArmServerStorage(d *pluginsdk.ResourceData) *servers.Storage {
storage.AutoGrow = &autoGrow

if v, ok := d.GetOk("storage_mb"); ok {
storage.StorageSizeGB = utils.Int64(int64(v.(int) / 1024))
storage.StorageSizeGB = pointer.FromInt64(int64(v.(int) / 1024))
}

if v, ok := d.GetOk("storage_tier"); ok {
storage.Tier = pointer.To(servers.AzureManagedDiskPerformanceTiers(v.(string)))
}

return &storage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package postgres_test
import (
"context"
"fmt"
"regexp"
"testing"
"time"

Expand All @@ -29,6 +30,8 @@ func TestAccPostgresqlFlexibleServer_basic(t *testing.T) {
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("fqdn").Exists(),
check.That(data.ResourceName).Key("public_network_access_enabled").Exists(),
check.That(data.ResourceName).Key("storage_mb").HasValue("32768"),
check.That(data.ResourceName).Key("storage_tier").HasValue("P4"),
),
},
data.ImportStep("administrator_password", "create_mode"),
Expand Down Expand Up @@ -75,6 +78,8 @@ func TestAccPostgresqlFlexibleServer_completeUpdate(t *testing.T) {
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("fqdn").Exists(),
check.That(data.ResourceName).Key("public_network_access_enabled").Exists(),
check.That(data.ResourceName).Key("storage_tier").HasValue("P4"),
check.That(data.ResourceName).Key("storage_mb").HasValue("32768"),
),
},
data.ImportStep("administrator_password", "create_mode"),
Expand All @@ -84,6 +89,8 @@ func TestAccPostgresqlFlexibleServer_completeUpdate(t *testing.T) {
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("fqdn").Exists(),
check.That(data.ResourceName).Key("public_network_access_enabled").Exists(),
check.That(data.ResourceName).Key("storage_tier").HasValue("P6"),
check.That(data.ResourceName).Key("storage_mb").HasValue("65536"),
),
},
data.ImportStep("administrator_password", "create_mode"),
Expand Down Expand Up @@ -410,6 +417,93 @@ func TestAccPostgresqlFlexibleServer_autoGrowEnabled(t *testing.T) {
})
}

func TestAccPostgresqlFlexibleServer_invalidStorageTier(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_postgresql_flexible_server", "test")
r := PostgresqlFlexibleServerResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.invalidStorageTier(data),
ExpectError: regexp.MustCompile("invalid 'storage_tier'"),
},
})
}

func TestAccPostgresqlFlexibleServer_invalidStorageMbScaling(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_postgresql_flexible_server", "test")
r := PostgresqlFlexibleServerResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.invalidStorageMbScaling(data, "524288"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("administrator_password", "create_mode"),
{
Config: r.invalidStorageMbScaling(data, "262144"),
ExpectError: regexp.MustCompile("'storage_mb' can only be scaled up"),
},
})
}

func TestAccPostgresqlFlexibleServer_invalidStorageTierScalingStorageMb(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_postgresql_flexible_server", "test")
r := PostgresqlFlexibleServerResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.invalidStorageTierScaling(data, "P4", "32768"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("administrator_password", "create_mode"),
{
Config: r.invalidStorageTierScaling(data, "P4", "262144"),
ExpectError: regexp.MustCompile("invalid 'storage_tier'"),
},
})
}

func TestAccPostgresqlFlexibleServer_invalidStorageTierScalingStorageTier(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_postgresql_flexible_server", "test")
r := PostgresqlFlexibleServerResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.invalidStorageTierScaling(data, "P4", "32768"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("administrator_password", "create_mode"),
{
Config: r.invalidStorageTierScaling(data, "P80", "32768"),
ExpectError: regexp.MustCompile("invalid 'storage_tier'"),
},
})
}

func TestAccPostgresqlFlexibleServer_invalidStorageTierScalingStorageMbStorageTier(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_postgresql_flexible_server", "test")
r := PostgresqlFlexibleServerResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.invalidStorageTierScaling(data, "P4", "32768"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("administrator_password", "create_mode"),
{
Config: r.invalidStorageTierScaling(data, "P6", "131072"),
ExpectError: regexp.MustCompile("invalid 'storage_tier'"),
},
})
}

func (PostgresqlFlexibleServerResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := servers.ParseFlexibleServerID(state.ID)
if err != nil {
Expand Down Expand Up @@ -447,7 +541,6 @@ resource "azurerm_postgresql_flexible_server" "test" {
location = azurerm_resource_group.test.location
administrator_login = "adminTerraform"
administrator_password = "QAZwsx123"
storage_mb = 32768
version = "12"
sku_name = "GP_Standard_D2s_v3"
zone = "2"
Expand Down Expand Up @@ -600,6 +693,7 @@ resource "azurerm_postgresql_flexible_server" "test" {
version = "13"
backup_retention_days = 10
storage_mb = 65536
storage_tier = "P6"
delegated_subnet_id = azurerm_subnet.test.id
private_dns_zone_id = azurerm_private_dns_zone.test.id
sku_name = "GP_Standard_D2s_v3"
Expand Down Expand Up @@ -1055,3 +1149,60 @@ resource "azurerm_postgresql_flexible_server" "test" {
}
`, r.template(data), data.RandomInteger, autoGrowEnabled)
}

func (r PostgresqlFlexibleServerResource) invalidStorageTier(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_postgresql_flexible_server" "test" {
name = "acctest-fs-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
administrator_login = "adminTerraform"
administrator_password = "QAZwsx123"
storage_mb = 65536
storage_tier = "P4"
version = "12"
sku_name = "GP_Standard_D2s_v3"
zone = "2"
}
`, r.template(data), data.RandomInteger)
}

func (r PostgresqlFlexibleServerResource) invalidStorageMbScaling(data acceptance.TestData, storageMb string) string {
return fmt.Sprintf(`
%s
resource "azurerm_postgresql_flexible_server" "test" {
name = "acctest-fs-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
administrator_login = "adminTerraform"
administrator_password = "QAZwsx123"
storage_mb = %s
storage_tier = "P20"
version = "12"
sku_name = "GP_Standard_D2s_v3"
zone = "2"
}
`, r.template(data), data.RandomInteger, storageMb)
}

func (r PostgresqlFlexibleServerResource) invalidStorageTierScaling(data acceptance.TestData, storageTier string, storageMb string) string {
return fmt.Sprintf(`
%s
resource "azurerm_postgresql_flexible_server" "test" {
name = "acctest-fs-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
administrator_login = "adminTerraform"
administrator_password = "QAZwsx123"
storage_mb = %s
storage_tier = "%s"
version = "12"
sku_name = "GP_Standard_D2s_v3"
zone = "2"
}
`, r.template(data), data.RandomInteger, storageMb, storageTier)
}
Loading

0 comments on commit 3721fe5

Please sign in to comment.