From dcf32586e80a12a20b5f979a934dcf1dc60eecf5 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Fri, 22 Mar 2024 14:20:26 -0700 Subject: [PATCH] `azurerm_mssql_database` - add support for `secondary_type` (#25360) --- .../services/mssql/mssql_database_resource.go | 18 ++++- .../mssql/mssql_database_resource_test.go | 81 +++++++++++++++++++ website/docs/r/mssql_database.html.markdown | 2 + 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/internal/services/mssql/mssql_database_resource.go b/internal/services/mssql/mssql_database_resource.go index 783449a8af7c..6288a0062cae 100644 --- a/internal/services/mssql/mssql_database_resource.go +++ b/internal/services/mssql/mssql_database_resource.go @@ -284,6 +284,7 @@ func resourceMsSqlDatabaseCreate(d *pluginsdk.ResourceData, meta interface{}) er ZoneRedundant: pointer.To(d.Get("zone_redundant").(bool)), IsLedgerOn: pointer.To(ledgerEnabled), EncryptionProtectorAutoRotation: pointer.To(d.Get("transparent_data_encryption_key_automatic_rotation_enabled").(bool)), + SecondaryType: pointer.To(databases.SecondaryType(d.Get("secondary_type").(string))), }, Tags: tags.Expand(d.Get("tags").(map[string]interface{})), @@ -951,7 +952,6 @@ func resourceMsSqlDatabaseUpdate(d *pluginsdk.ResourceData, meta interface{}) er return nil } } - } if d.HasChange("import") { @@ -1091,12 +1091,19 @@ func resourceMsSqlDatabaseRead(d *pluginsdk.ResourceData, meta interface{}) erro requestedBackupStorageRedundancy = string(*props.RequestedBackupStorageRedundancy) } + // A named replica doesn't return props.RequestedBackupStorageRedundancy from the api but it is Geo in the portal regardless of what the parent database has + // so we'll copy that here to get around a perpetual diff + if props.SecondaryType != nil && *props.SecondaryType == "Named" { + requestedBackupStorageRedundancy = string(databases.BackupStorageRedundancyGeo) + } + d.Set("auto_pause_delay_in_minutes", pointer.From(props.AutoPauseDelay)) d.Set("collation", pointer.From(props.Collation)) d.Set("read_replica_count", pointer.From(props.HighAvailabilityReplicaCount)) d.Set("storage_account_type", requestedBackupStorageRedundancy) d.Set("zone_redundant", pointer.From(props.ZoneRedundant)) d.Set("read_scale", pointer.From(props.ReadScale) == databases.DatabaseReadScaleEnabled) + d.Set("secondary_type", pointer.From(props.SecondaryType)) if props.ElasticPoolId != nil { elasticPoolId = pointer.From(props.ElasticPoolId) @@ -1729,6 +1736,15 @@ func resourceMsSqlDatabaseSchema() map[string]*pluginsdk.Schema { RequiredWith: []string{"transparent_data_encryption_key_vault_key_id"}, }, + "secondary_type": { + Type: pluginsdk.TypeString, + Optional: true, + // This must be Computed as it has defaulted to Geo for replicas but not all databases are replicas. + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(databases.PossibleValuesForSecondaryType(), false), + }, + "tags": commonschema.Tags(), } } diff --git a/internal/services/mssql/mssql_database_resource_test.go b/internal/services/mssql/mssql_database_resource_test.go index 0dc4bf251764..73134aebdfda 100644 --- a/internal/services/mssql/mssql_database_resource_test.go +++ b/internal/services/mssql/mssql_database_resource_test.go @@ -920,6 +920,46 @@ func TestAccMsSqlDatabase_transparentDataEncryptionKey(t *testing.T) { }) } +func TestAccMsSqlDatabase_namedReplication(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_database", "test") + r := MsSqlDatabaseResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.hs(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("enclave_type").IsEmpty(), + ), + }, + data.ImportStep(), + { + Config: r.namedReplication(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("enclave_type").IsEmpty(), + ), + }, + data.ImportStep(), + }) +} + +func TestAccMsSqlDatabase_namedReplicationZoneRedundant(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_database", "test") + r := MsSqlDatabaseResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.namedReplicationZoneRedundant(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("enclave_type").IsEmpty(), + ), + }, + data.ImportStep(), + }) +} + func (MsSqlDatabaseResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := commonids.ParseSqlDatabaseID(state.ID) if err != nil { @@ -2079,3 +2119,44 @@ resource "azurerm_mssql_database" "test" { } `, r.template(data), data.RandomInteger, data.RandomString) } + +func (r MsSqlDatabaseResource) namedReplication(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_database" "secondary" { + name = "acctest-dbs2-%[2]d" + server_id = azurerm_mssql_server.test.id + create_mode = "Secondary" + secondary_type = "Named" + creation_source_database_id = azurerm_mssql_database.test.id +} +`, r.hs(data), data.RandomInteger) +} + +func (r MsSqlDatabaseResource) namedReplicationZoneRedundant(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_database" "test" { + name = "acctest-db-%[2]d" + server_id = azurerm_mssql_server.test.id + read_replica_count = 2 + sku_name = "HS_Gen5_2" + + storage_account_type = "Zone" + zone_redundant = true +} + +resource "azurerm_mssql_database" "secondary" { + name = "acctest-dbs2-%[2]d" + server_id = azurerm_mssql_server.test.id + create_mode = "Secondary" + secondary_type = "Named" + creation_source_database_id = azurerm_mssql_database.test.id + + zone_redundant = true + read_replica_count = 1 +} +`, r.template(data), data.RandomInteger) +} diff --git a/website/docs/r/mssql_database.html.markdown b/website/docs/r/mssql_database.html.markdown index f6aae7f04a89..14e45f6a8c2b 100644 --- a/website/docs/r/mssql_database.html.markdown +++ b/website/docs/r/mssql_database.html.markdown @@ -256,6 +256,8 @@ The following arguments are supported: * `zone_redundant` - (Optional) Whether or not this database is zone redundant, which means the replicas of this database will be spread across multiple availability zones. This property is only settable for Premium and Business Critical databases. +* `secondary_type` - (Optional) How do you want your replica to be made? Valid values include `Geo` and `Named`. Defaults to `Geo`. Changing this forces a new resource to be created. + * `tags` - (Optional) A mapping of tags to assign to the resource. ---