From 46066d3d311329e3dbb4c686f4cd8828e83f705f Mon Sep 17 00:00:00 2001 From: Mohit Ahuja Date: Mon, 29 Mar 2021 16:05:16 -0400 Subject: [PATCH] Adding ability to manage Geo backup policies for Data warehouse DBs --- .../internal/services/mssql/client/client.go | 4 ++ .../services/mssql/mssql_database_resource.go | 53 +++++++++++++++++++ .../mssql/mssql_database_resource_test.go | 50 +++++++++++++++++ website/docs/r/mssql_database.html.markdown | 4 ++ 4 files changed, 111 insertions(+) diff --git a/azurerm/internal/services/mssql/client/client.go b/azurerm/internal/services/mssql/client/client.go index 17ad92dadd52b..593b6f185148f 100644 --- a/azurerm/internal/services/mssql/client/client.go +++ b/azurerm/internal/services/mssql/client/client.go @@ -25,6 +25,7 @@ type Client struct { ServersClient *sql.ServersClient VirtualMachinesClient *sqlvirtualmachine.SQLVirtualMachinesClient VirtualNetworkRulesClient *sql.VirtualNetworkRulesClient + GeoBackupPoliciesClient *sql.GeoBackupPoliciesClient } func NewClient(o *common.ClientOptions) *Client { @@ -78,6 +79,8 @@ func NewClient(o *common.ClientOptions) *Client { sqlVirtualNetworkRulesClient := sql.NewVirtualNetworkRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&sqlVirtualNetworkRulesClient.Client, o.ResourceManagerAuthorizer) + geoBackupPoliciesClient := sql.NewGeoBackupPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&geoBackupPoliciesClient.Client, o.ResourceManagerAuthorizer) return &Client{ BackupLongTermRetentionPoliciesClient: &BackupLongTermRetentionPoliciesClient, @@ -97,5 +100,6 @@ func NewClient(o *common.ClientOptions) *Client { ServerVulnerabilityAssessmentsClient: &serverVulnerabilityAssessmentsClient, VirtualMachinesClient: &sqlVirtualMachinesClient, VirtualNetworkRulesClient: &sqlVirtualNetworkRulesClient, + GeoBackupPoliciesClient: &geoBackupPoliciesClient, } } diff --git a/azurerm/internal/services/mssql/mssql_database_resource.go b/azurerm/internal/services/mssql/mssql_database_resource.go index 93ac7c58b3f38..0f03956e6859a 100644 --- a/azurerm/internal/services/mssql/mssql_database_resource.go +++ b/azurerm/internal/services/mssql/mssql_database_resource.go @@ -292,6 +292,12 @@ func resourceMsSqlDatabase() *schema.Resource { }, }, + "geo_backup_policy": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "tags": tags.Schema(), }, @@ -311,6 +317,8 @@ func resourceMsSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{}) threatClient := meta.(*clients.Client).MSSQL.DatabaseThreatDetectionPoliciesClient longTermRetentionClient := meta.(*clients.Client).MSSQL.BackupLongTermRetentionPoliciesClient shortTermRetentionClient := meta.(*clients.Client).MSSQL.BackupShortTermRetentionPoliciesClient + geoBackupPoliciesClient := meta.(*clients.Client).MSSQL.GeoBackupPoliciesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -444,6 +452,30 @@ func resourceMsSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{}) d.SetId(*read.ID) + // For datawarehouse SKUs, set the geo-backup policy + if d.HasChange("geo_backup_policy") && strings.HasPrefix(skuName.(string), "DW") { + v := d.Get("geo_backup_policy").(bool) + + var geoBackupPolicyState sql.GeoBackupPolicyState + + if v { + geoBackupPolicyState = sql.GeoBackupPolicyStateEnabled + } else { + geoBackupPolicyState = sql.GeoBackupPolicyStateDisabled + } + + geoBackupPolicy := sql.GeoBackupPolicy{ + GeoBackupPolicyProperties: &sql.GeoBackupPolicyProperties{ + State: geoBackupPolicyState, + }, + } + + _, err := geoBackupPoliciesClient.CreateOrUpdate(ctx, serverId.ResourceGroup, serverId.Name, name, geoBackupPolicy) + if err != nil { + return fmt.Errorf("Error issuing create/update request for Sql Server %q (Database %q) Geo backup policies (Resource Group %q): %+v", serverId.Name, name, serverId.ResourceGroup, err) + } + } + if _, err = threatClient.CreateOrUpdate(ctx, serverId.ResourceGroup, serverId.Name, name, *expandMsSqlServerThreatDetectionPolicy(d, location)); err != nil { return fmt.Errorf("setting database threat detection policy: %+v", err) } @@ -509,6 +541,7 @@ func resourceMsSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error { auditingClient := meta.(*clients.Client).MSSQL.DatabaseExtendedBlobAuditingPoliciesClient longTermRetentionClient := meta.(*clients.Client).MSSQL.BackupLongTermRetentionPoliciesClient shortTermRetentionClient := meta.(*clients.Client).MSSQL.BackupShortTermRetentionPoliciesClient + geoBackupPoliciesClient := meta.(*clients.Client).MSSQL.GeoBackupPoliciesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -577,6 +610,8 @@ func resourceMsSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("failure in setting `extended_auditing_policy`: %+v", err) } + geoBackupPolicy := true + // Hyper Scale SKU's do not currently support LRP and do not honour normal SRP operations if !strings.HasPrefix(skuName, "HS") && !strings.HasPrefix(skuName, "DW") { longTermPolicy, err := longTermRetentionClient.Get(ctx, id.ResourceGroup, id.ServerName, id.Name) @@ -602,6 +637,24 @@ func resourceMsSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error { zero := make([]interface{}, 0) d.Set("long_term_retention_policy", zero) d.Set("short_term_retention_policy", zero) + + geoPoliciesResponse, err := geoBackupPoliciesClient.Get(ctx, id.ResourceGroup, id.ServerName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("reading MsSql Database %s (MsSql Server Name %q / Resource Group %q): %s", id.Name, id.ServerName, id.ResourceGroup, err) + } + + // For Datawarehouse SKUs, set the geo-backup policy setting + if strings.HasPrefix(skuName, "DW") && geoPoliciesResponse.GeoBackupPolicyProperties != nil && geoPoliciesResponse.GeoBackupPolicyProperties.State == sql.GeoBackupPolicyStateDisabled { + geoBackupPolicy = false + } + } + + if err := d.Set("geo_backup_policy", geoBackupPolicy); err != nil { + return fmt.Errorf("failure in setting `geo_backup_policy`: %+v", err) } return tags.FlattenAndSet(d, resp.Tags) diff --git a/azurerm/internal/services/mssql/mssql_database_resource_test.go b/azurerm/internal/services/mssql/mssql_database_resource_test.go index 7f92020664535..6df244c80bf3d 100644 --- a/azurerm/internal/services/mssql/mssql_database_resource_test.go +++ b/azurerm/internal/services/mssql/mssql_database_resource_test.go @@ -541,6 +541,30 @@ func TestAccMsSqlDatabase_withShortTermRetentionPolicy(t *testing.T) { }) } +func TestAccMsSqlDatabase_geoBackupPolicy(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_database", "test") + r := MsSqlDatabaseResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.withGeoBackupPoliciesEnabled(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("geo_backup_policy").HasValue("true"), + ), + }, + data.ImportStep(), + { + Config: r.withGeoBackupPoliciesDisabled(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("geo_backup_policy").HasValue("false"), + ), + }, + data.ImportStep(), + }) +} + func (MsSqlDatabaseResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.DatabaseID(state.ID) if err != nil { @@ -1352,3 +1376,29 @@ resource "azurerm_mssql_database" "test" { } `, r.template(data), data.RandomIntOfLength(15), data.RandomInteger) } + +func (r MsSqlDatabaseResource) withGeoBackupPoliciesEnabled(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_database" "test" { + name = "acctest-db-%[3]d" + server_id = azurerm_sql_server.test.id + sku_name = "DW100c" + geo_backup_policy = true +} +`, r.template(data), data.RandomIntOfLength(15), data.RandomInteger) +} + +func (r MsSqlDatabaseResource) withGeoBackupPoliciesDisabled(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_database" "test" { + name = "acctest-db-%[3]d" + server_id = azurerm_sql_server.test.id + sku_name = "DW100c" + geo_backup_policy = false +} +`, r.template(data), data.RandomIntOfLength(15), data.RandomInteger) +} diff --git a/website/docs/r/mssql_database.html.markdown b/website/docs/r/mssql_database.html.markdown index 68a2736d03adb..52aa537fa5bdf 100644 --- a/website/docs/r/mssql_database.html.markdown +++ b/website/docs/r/mssql_database.html.markdown @@ -88,6 +88,10 @@ The following arguments are supported: * `extended_auditing_policy` - (Optional) A `extended_auditing_policy` block as defined below. +* `geo_backup_policy` - (Optional) Boolean that specifies if a Data Warehouse db has geo backup policy set to Enabled or Disabled + +~> **NOTE** Only applicable when SKU starts with 'DW' (Data Warehouse) + * `license_type` - (Optional) Specifies the license type applied to this database. Possible values are `LicenseIncluded` and `BasePrice`. * `long_term_retention_policy` - (Optional) A `long_term_retention_policy` block as defined below.