From 74c1cd099ab45b3722acf064e39804ea329f156a Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 15 Feb 2024 13:17:25 -0800 Subject: [PATCH 1/4] azurerm_mssql_database - support for recovery_point_id --- .../log_analytics_workspace_resource.go | 4 ++-- .../services/mssql/mssql_database_resource.go | 19 +++++++++++++++++++ website/docs/r/mssql_database.html.markdown | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/internal/services/loganalytics/log_analytics_workspace_resource.go b/internal/services/loganalytics/log_analytics_workspace_resource.go index 3c79c1330b1f..6cb3af734711 100644 --- a/internal/services/loganalytics/log_analytics_workspace_resource.go +++ b/internal/services/loganalytics/log_analytics_workspace_resource.go @@ -538,8 +538,8 @@ func resourceLogAnalyticsWorkspaceDelete(d *pluginsdk.ResourceData, meta interfa return err } - PermanentlyDeleteOnDestroy := meta.(*clients.Client).Features.LogAnalyticsWorkspace.PermanentlyDeleteOnDestroy - err = client.DeleteThenPoll(ctx, sharedKeyId, sharedKeyWorkspaces.DeleteOperationOptions{Force: utils.Bool(PermanentlyDeleteOnDestroy)}) + permanentlyDeleteOnDestroy := meta.(*clients.Client).Features.LogAnalyticsWorkspace.PermanentlyDeleteOnDestroy + err = client.DeleteThenPoll(ctx, sharedKeyId, sharedKeyWorkspaces.DeleteOperationOptions{Force: utils.Bool(permanentlyDeleteOnDestroy)}) if err != nil { return fmt.Errorf("issuing AzureRM delete request for Log Analytics Workspaces '%s': %+v", id.WorkspaceName, err) } diff --git a/internal/services/mssql/mssql_database_resource.go b/internal/services/mssql/mssql_database_resource.go index c8d0a4a7a711..f27b8d7b8cf5 100644 --- a/internal/services/mssql/mssql_database_resource.go +++ b/internal/services/mssql/mssql_database_resource.go @@ -324,6 +324,10 @@ func resourceMsSqlDatabaseCreate(d *pluginsdk.ResourceData, meta interface{}) er if _, dbok := d.GetOk("restore_dropped_database_id"); !dbok { return fmt.Errorf("'restore_dropped_database_id' is required for create_mode %s", createMode) } + case databases.CreateModeRestoreLongTermRetentionBackup: + if _, dbok := d.GetOk("recovery_point_id"); !dbok { + return fmt.Errorf("'recovery_point_id' is required for create_mode %s", createMode) + } } // we should not specify the value of `maintenance_configuration_name` when `elastic_pool_id` is set since its value depends on the elastic pool's `maintenance_configuration_name` value. @@ -377,6 +381,10 @@ func resourceMsSqlDatabaseCreate(d *pluginsdk.ResourceData, meta interface{}) er input.Properties.RecoverableDatabaseId = pointer.To(v.(string)) } + if v, ok := d.GetOk("recovery_point_id"); ok { + input.Properties.RecoveryServicesRecoveryPointId = pointer.To(v.(string)) + } + if v, ok := d.GetOk("restore_dropped_database_id"); ok { input.Properties.RestorableDroppedDatabaseId = pointer.To(v.(string)) } @@ -1004,6 +1012,10 @@ func resourceMsSqlDatabaseUpdate(d *pluginsdk.ResourceData, meta interface{}) er props.RecoverableDatabaseId = pointer.To(d.Get("recover_database_id").(string)) } + if d.HasChange("recovery_point_id") { + props.RecoveryServicesRecoveryPointId = pointer.To(d.Get("recover_database_id").(string)) + } + if d.HasChange("restore_dropped_database_id") { props.RestorableDroppedDatabaseId = pointer.To(d.Get("restore_dropped_database_id").(string)) } @@ -1412,6 +1424,7 @@ func resourceMsSqlDatabaseSchema() map[string]*pluginsdk.Schema { false), ConflictsWith: []string{"import"}, }, + "import": { Type: pluginsdk.TypeList, Optional: true, @@ -1522,6 +1535,12 @@ func resourceMsSqlDatabaseSchema() map[string]*pluginsdk.Schema { ValidateFunc: validate.RecoverableDatabaseID, }, + "recovery_point_id": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "restore_dropped_database_id": { Type: pluginsdk.TypeString, Optional: true, diff --git a/website/docs/r/mssql_database.html.markdown b/website/docs/r/mssql_database.html.markdown index 31af12f412ee..f5c23a4ed360 100644 --- a/website/docs/r/mssql_database.html.markdown +++ b/website/docs/r/mssql_database.html.markdown @@ -220,6 +220,8 @@ The following arguments are supported: * `recover_database_id` - (Optional) The ID of the database to be recovered. This property is only applicable when the `create_mode` is `Recovery`. +* `recovery_point_id` - (Optional) The ID of the Recovery Services Recovery Point Id to be restored. This property is only applicable when the `create_mode` is `CreateModeRestoreLongTermRetentionBackup`. + * `restore_dropped_database_id` - (Optional) The ID of the database to be restored. This property is only applicable when the `create_mode` is `Restore`. * `read_replica_count` - (Optional) The number of readonly secondary replicas associated with the database to which readonly application intent connections may be routed. This property is only settable for Hyperscale edition databases. From 16fb2eb35e79cc95137f4bd9dd6b2f7bf9c2b857 Mon Sep 17 00:00:00 2001 From: kt Date: Tue, 20 Feb 2024 07:26:28 -0800 Subject: [PATCH 2/4] Update internal/services/mssql/mssql_database_resource.go Co-authored-by: catriona-m <86247157+catriona-m@users.noreply.github.com> --- internal/services/mssql/mssql_database_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/mssql/mssql_database_resource.go b/internal/services/mssql/mssql_database_resource.go index f27b8d7b8cf5..a85b42df912d 100644 --- a/internal/services/mssql/mssql_database_resource.go +++ b/internal/services/mssql/mssql_database_resource.go @@ -1013,7 +1013,7 @@ func resourceMsSqlDatabaseUpdate(d *pluginsdk.ResourceData, meta interface{}) er } if d.HasChange("recovery_point_id") { - props.RecoveryServicesRecoveryPointId = pointer.To(d.Get("recover_database_id").(string)) + props.RecoveryServicesRecoveryPointId = pointer.To(d.Get("recovery_point_id").(string)) } if d.HasChange("restore_dropped_database_id") { From 759e2ee325a2359a33b71515ce03646a260f92f2 Mon Sep 17 00:00:00 2001 From: kt Date: Wed, 21 Feb 2024 17:59:48 -0800 Subject: [PATCH 3/4] add nother property --- .../kubernetes_fleet_manager_resource_gen.go | 3 + .../services/mssql/mssql_database_resource.go | 398 +++++++++--------- 2 files changed, 209 insertions(+), 192 deletions(-) diff --git a/internal/services/containers/kubernetes_fleet_manager_resource_gen.go b/internal/services/containers/kubernetes_fleet_manager_resource_gen.go index 4746a9f91a38..2b9172eb6575 100644 --- a/internal/services/containers/kubernetes_fleet_manager_resource_gen.go +++ b/internal/services/containers/kubernetes_fleet_manager_resource_gen.go @@ -49,7 +49,9 @@ func (r KubernetesFleetManagerResource) Arguments() map[string]*pluginsdk.Schema Required: true, Type: pluginsdk.TypeString, }, + "resource_group_name": commonschema.ResourceGroupName(), + "hub_profile": { Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ @@ -72,6 +74,7 @@ func (r KubernetesFleetManagerResource) Arguments() map[string]*pluginsdk.Schema Optional: true, Type: pluginsdk.TypeList, }, + "tags": commonschema.Tags(), } } diff --git a/internal/services/mssql/mssql_database_resource.go b/internal/services/mssql/mssql_database_resource.go index f27b8d7b8cf5..a172c3e3797e 100644 --- a/internal/services/mssql/mssql_database_resource.go +++ b/internal/services/mssql/mssql_database_resource.go @@ -325,8 +325,8 @@ func resourceMsSqlDatabaseCreate(d *pluginsdk.ResourceData, meta interface{}) er return fmt.Errorf("'restore_dropped_database_id' is required for create_mode %s", createMode) } case databases.CreateModeRestoreLongTermRetentionBackup: - if _, dbok := d.GetOk("recovery_point_id"); !dbok { - return fmt.Errorf("'recovery_point_id' is required for create_mode %s", createMode) + if _, dbok := d.GetOk("long_term_retention_backup_id"); !dbok { + return fmt.Errorf("'long_term_retention_backup_id' is required for create_mode %s", createMode) } } @@ -389,6 +389,10 @@ func resourceMsSqlDatabaseCreate(d *pluginsdk.ResourceData, meta interface{}) er input.Properties.RestorableDroppedDatabaseId = pointer.To(v.(string)) } + if v, ok := d.GetOk("restore_long_term_retention_backup_id"); ok { + input.Properties.LongTermRetentionBackupResourceId = pointer.To(v.(string)) + } + if v, ok := d.GetOk("identity"); ok { expandedIdentity, err := identity.ExpandUserAssignedMap(v.([]interface{})) if err != nil { @@ -590,196 +594,6 @@ func resourceMsSqlDatabaseCreate(d *pluginsdk.ResourceData, meta interface{}) er return resourceMsSqlDatabaseRead(d, meta) } -func resourceMsSqlDatabaseRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).MSSQL.DatabasesClient - securityAlertPoliciesClient := meta.(*clients.Client).MSSQL.DatabaseSecurityAlertPoliciesClient - - longTermRetentionClient := meta.(*clients.Client).MSSQL.LongTermRetentionPoliciesClient - shortTermRetentionClient := meta.(*clients.Client).MSSQL.BackupShortTermRetentionPoliciesClient - geoBackupPoliciesClient := meta.(*clients.Client).MSSQL.GeoBackupPoliciesClient - transparentEncryptionClient := meta.(*clients.Client).MSSQL.TransparentDataEncryptionsClient - - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := commonids.ParseSqlDatabaseID(d.Id()) - if err != nil { - return err - } - - serverId := commonids.NewSqlServerID(id.SubscriptionId, id.ResourceGroupName, id.ServerName) - d.Set("server_id", serverId.ID()) - - resp, err := client.Get(ctx, pointer.From(id), databases.DefaultGetOperationOptions()) - if err != nil { - if response.WasNotFound(resp.HttpResponse) { - d.SetId("") - return nil - } - return fmt.Errorf("retrieving %s: %+v", id, err) - } - - geoBackupPolicy := true - skuName := "" - elasticPoolId := "" - minCapacity := float64(0) - ledgerEnabled := false - enclaveType := "" - - if model := resp.Model; model != nil { - d.Set("name", id.DatabaseName) - - if props := model.Properties; props != nil { - minCapacity = pointer.From(props.MinCapacity) - - requestedBackupStorageRedundancy := "" - if props.RequestedBackupStorageRedundancy != nil { - requestedBackupStorageRedundancy = string(*props.RequestedBackupStorageRedundancy) - } - - 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) - - if props.ElasticPoolId != nil { - elasticPoolId = pointer.From(props.ElasticPoolId) - } - - if props.LicenseType != nil { - d.Set("license_type", string(pointer.From(props.LicenseType))) - } else { - // value not returned, try to set from state - d.Set("license_type", d.Get("license_type").(string)) - } - - if props.MaxSizeBytes != nil { - d.Set("max_size_gb", int32((*props.MaxSizeBytes)/int64(1073741824))) - } - - if props.CurrentServiceObjectiveName != nil { - skuName = *props.CurrentServiceObjectiveName - } - - if props.IsLedgerOn != nil { - ledgerEnabled = *props.IsLedgerOn - } - - // NOTE: Always set the PreferredEnclaveType to an empty string unless it isn't 'Default'... - if v := props.PreferredEnclaveType; v != nil && pointer.From(v) != databases.AlwaysEncryptedEnclaveTypeDefault { - enclaveType = string(pointer.From(v)) - } - - configurationName := "" - if v := props.MaintenanceConfigurationId; v != nil { - maintenanceConfigId, err := publicmaintenanceconfigurations.ParsePublicMaintenanceConfigurationIDInsensitively(pointer.From(v)) - if err != nil { - return err - } - configurationName = maintenanceConfigId.PublicMaintenanceConfigurationName - } - - d.Set("elastic_pool_id", elasticPoolId) - d.Set("min_capacity", minCapacity) - d.Set("sku_name", skuName) - d.Set("maintenance_configuration_name", configurationName) - d.Set("ledger_enabled", ledgerEnabled) - d.Set("enclave_type", enclaveType) - d.Set("transparent_data_encryption_key_vault_key_id", props.EncryptionProtector) - d.Set("transparent_data_encryption_key_automatic_rotation_enabled", pointer.From(props.EncryptionProtectorAutoRotation)) - - identity, err := identity.FlattenUserAssignedMap(model.Identity) - if err != nil { - return fmt.Errorf("setting `identity`: %+v", err) - } - - if err := d.Set("identity", identity); err != nil { - return fmt.Errorf("setting `identity`: %+v", err) - } - - if err := tags.FlattenAndSet(d, model.Tags); err != nil { - return err - } - } - - // DW SKU's do not currently support LRP and do not honour normal SRP operations - if !strings.HasPrefix(skuName, "DW") { - longTermPolicy, err := longTermRetentionClient.Get(ctx, pointer.From(id)) - if err != nil { - return fmt.Errorf("retrieving Long Term Retention Policies for %s: %+v", id, err) - } - - if model := longTermPolicy.Model; model != nil { - if err := d.Set("long_term_retention_policy", helper.FlattenLongTermRetentionPolicy(model)); err != nil { - return fmt.Errorf("setting `long_term_retention_policy`: %+v", err) - } - } - - shortTermPolicy, err := shortTermRetentionClient.Get(ctx, pointer.From(id)) - - if model := shortTermPolicy.Model; model != nil { - if err != nil { - return fmt.Errorf("retrieving Short Term Retention Policies for %s: %+v", id, err) - } - - if err := d.Set("short_term_retention_policy", helper.FlattenShortTermRetentionPolicy(model)); err != nil { - return fmt.Errorf("setting `short_term_retention_policy`: %+v", err) - } - } - } else { - // DW SKUs need the retention policies to be empty for state consistency - emptySlice := make([]interface{}, 0) - d.Set("long_term_retention_policy", emptySlice) - d.Set("short_term_retention_policy", emptySlice) - - geoPoliciesResponse, err := geoBackupPoliciesClient.Get(ctx, pointer.From(id)) - if err != nil { - if response.WasNotFound(geoPoliciesResponse.HttpResponse) { - d.SetId("") - return nil - } - - return fmt.Errorf("retrieving Geo Backup Policies for %s: %+v", id, err) - } - - // For Datawarehouse SKUs, set the geo-backup policy setting - if model := geoPoliciesResponse.Model; model != nil { - if strings.HasPrefix(skuName, "DW") && model.Properties.State == geobackuppolicies.GeoBackupPolicyStateDisabled { - geoBackupPolicy = false - } - } - } - } - - if err := d.Set("geo_backup_enabled", geoBackupPolicy); err != nil { - return fmt.Errorf("setting `geo_backup_enabled`: %+v", err) - } - - securityAlertPolicy, err := securityAlertPoliciesClient.Get(ctx, pointer.From(id)) - if err == nil && securityAlertPolicy.Model != nil { - if err := d.Set("threat_detection_policy", flattenMsSqlServerSecurityAlertPolicy(d, pointer.From(securityAlertPolicy.Model))); err != nil { - return fmt.Errorf("setting `threat_detection_policy`: %+v", err) - } - } - - tde, err := transparentEncryptionClient.Get(ctx, pointer.From(id)) - if err != nil { - return fmt.Errorf("while retrieving Transparent Data Encryption state for %s: %+v", id, err) - } - - tdeState := false - if model := tde.Model; model != nil { - if props := model.Properties; props != nil { - tdeState = (props.State == transparentdataencryptions.TransparentDataEncryptionStateEnabled) - } - } - d.Set("transparent_data_encryption_enabled", tdeState) - - return nil -} - func resourceMsSqlDatabaseUpdate(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).MSSQL.DatabasesClient serversClient := meta.(*clients.Client).MSSQL.ServersClient @@ -1020,6 +834,10 @@ func resourceMsSqlDatabaseUpdate(d *pluginsdk.ResourceData, meta interface{}) er props.RestorableDroppedDatabaseId = pointer.To(d.Get("restore_dropped_database_id").(string)) } + if d.HasChange("restore_long_term_retention_backup_id") { + props.LongTermRetentionBackupResourceId = pointer.To(d.Get("restore_long_term_retention_backup_id").(string)) + } + if d.HasChange("tags") { payload.Tags = tags.Expand(d.Get("tags").(map[string]interface{})) } @@ -1226,6 +1044,196 @@ func resourceMsSqlDatabaseUpdate(d *pluginsdk.ResourceData, meta interface{}) er return resourceMsSqlDatabaseRead(d, meta) } +func resourceMsSqlDatabaseRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).MSSQL.DatabasesClient + securityAlertPoliciesClient := meta.(*clients.Client).MSSQL.DatabaseSecurityAlertPoliciesClient + + longTermRetentionClient := meta.(*clients.Client).MSSQL.LongTermRetentionPoliciesClient + shortTermRetentionClient := meta.(*clients.Client).MSSQL.BackupShortTermRetentionPoliciesClient + geoBackupPoliciesClient := meta.(*clients.Client).MSSQL.GeoBackupPoliciesClient + transparentEncryptionClient := meta.(*clients.Client).MSSQL.TransparentDataEncryptionsClient + + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := commonids.ParseSqlDatabaseID(d.Id()) + if err != nil { + return err + } + + serverId := commonids.NewSqlServerID(id.SubscriptionId, id.ResourceGroupName, id.ServerName) + d.Set("server_id", serverId.ID()) + + resp, err := client.Get(ctx, pointer.From(id), databases.DefaultGetOperationOptions()) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + d.SetId("") + return nil + } + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + geoBackupPolicy := true + skuName := "" + elasticPoolId := "" + minCapacity := float64(0) + ledgerEnabled := false + enclaveType := "" + + if model := resp.Model; model != nil { + d.Set("name", id.DatabaseName) + + if props := model.Properties; props != nil { + minCapacity = pointer.From(props.MinCapacity) + + requestedBackupStorageRedundancy := "" + if props.RequestedBackupStorageRedundancy != nil { + requestedBackupStorageRedundancy = string(*props.RequestedBackupStorageRedundancy) + } + + 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) + + if props.ElasticPoolId != nil { + elasticPoolId = pointer.From(props.ElasticPoolId) + } + + if props.LicenseType != nil { + d.Set("license_type", string(pointer.From(props.LicenseType))) + } else { + // value not returned, try to set from state + d.Set("license_type", d.Get("license_type").(string)) + } + + if props.MaxSizeBytes != nil { + d.Set("max_size_gb", int32((*props.MaxSizeBytes)/int64(1073741824))) + } + + if props.CurrentServiceObjectiveName != nil { + skuName = *props.CurrentServiceObjectiveName + } + + if props.IsLedgerOn != nil { + ledgerEnabled = *props.IsLedgerOn + } + + // NOTE: Always set the PreferredEnclaveType to an empty string unless it isn't 'Default'... + if v := props.PreferredEnclaveType; v != nil && pointer.From(v) != databases.AlwaysEncryptedEnclaveTypeDefault { + enclaveType = string(pointer.From(v)) + } + + configurationName := "" + if v := props.MaintenanceConfigurationId; v != nil { + maintenanceConfigId, err := publicmaintenanceconfigurations.ParsePublicMaintenanceConfigurationIDInsensitively(pointer.From(v)) + if err != nil { + return err + } + configurationName = maintenanceConfigId.PublicMaintenanceConfigurationName + } + + d.Set("elastic_pool_id", elasticPoolId) + d.Set("min_capacity", minCapacity) + d.Set("sku_name", skuName) + d.Set("maintenance_configuration_name", configurationName) + d.Set("ledger_enabled", ledgerEnabled) + d.Set("enclave_type", enclaveType) + d.Set("transparent_data_encryption_key_vault_key_id", props.EncryptionProtector) + d.Set("transparent_data_encryption_key_automatic_rotation_enabled", pointer.From(props.EncryptionProtectorAutoRotation)) + + identity, err := identity.FlattenUserAssignedMap(model.Identity) + if err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + + if err := d.Set("identity", identity); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + + if err := tags.FlattenAndSet(d, model.Tags); err != nil { + return err + } + } + + // DW SKU's do not currently support LRP and do not honour normal SRP operations + if !strings.HasPrefix(skuName, "DW") { + longTermPolicy, err := longTermRetentionClient.Get(ctx, pointer.From(id)) + if err != nil { + return fmt.Errorf("retrieving Long Term Retention Policies for %s: %+v", id, err) + } + + if model := longTermPolicy.Model; model != nil { + if err := d.Set("long_term_retention_policy", helper.FlattenLongTermRetentionPolicy(model)); err != nil { + return fmt.Errorf("setting `long_term_retention_policy`: %+v", err) + } + } + + shortTermPolicy, err := shortTermRetentionClient.Get(ctx, pointer.From(id)) + + if model := shortTermPolicy.Model; model != nil { + if err != nil { + return fmt.Errorf("retrieving Short Term Retention Policies for %s: %+v", id, err) + } + + if err := d.Set("short_term_retention_policy", helper.FlattenShortTermRetentionPolicy(model)); err != nil { + return fmt.Errorf("setting `short_term_retention_policy`: %+v", err) + } + } + } else { + // DW SKUs need the retention policies to be empty for state consistency + emptySlice := make([]interface{}, 0) + d.Set("long_term_retention_policy", emptySlice) + d.Set("short_term_retention_policy", emptySlice) + + geoPoliciesResponse, err := geoBackupPoliciesClient.Get(ctx, pointer.From(id)) + if err != nil { + if response.WasNotFound(geoPoliciesResponse.HttpResponse) { + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving Geo Backup Policies for %s: %+v", id, err) + } + + // For Datawarehouse SKUs, set the geo-backup policy setting + if model := geoPoliciesResponse.Model; model != nil { + if strings.HasPrefix(skuName, "DW") && model.Properties.State == geobackuppolicies.GeoBackupPolicyStateDisabled { + geoBackupPolicy = false + } + } + } + } + + if err := d.Set("geo_backup_enabled", geoBackupPolicy); err != nil { + return fmt.Errorf("setting `geo_backup_enabled`: %+v", err) + } + + securityAlertPolicy, err := securityAlertPoliciesClient.Get(ctx, pointer.From(id)) + if err == nil && securityAlertPolicy.Model != nil { + if err := d.Set("threat_detection_policy", flattenMsSqlServerSecurityAlertPolicy(d, pointer.From(securityAlertPolicy.Model))); err != nil { + return fmt.Errorf("setting `threat_detection_policy`: %+v", err) + } + } + + tde, err := transparentEncryptionClient.Get(ctx, pointer.From(id)) + if err != nil { + return fmt.Errorf("while retrieving Transparent Data Encryption state for %s: %+v", id, err) + } + + tdeState := false + if model := tde.Model; model != nil { + if props := model.Properties; props != nil { + tdeState = (props.State == transparentdataencryptions.TransparentDataEncryptionStateEnabled) + } + } + d.Set("transparent_data_encryption_enabled", tdeState) + + return nil +} + func resourceMsSqlDatabaseDelete(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).MSSQL.DatabasesClient ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) @@ -1547,6 +1555,12 @@ func resourceMsSqlDatabaseSchema() map[string]*pluginsdk.Schema { ValidateFunc: validate.RestorableDatabaseID, }, + "restore_long_term_retention_backup_id": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "read_replica_count": { Type: pluginsdk.TypeInt, Optional: true, From d6fd106b9f1c3e6ad43d5808ce8a307b4e68e680 Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 22 Feb 2024 10:01:34 -0800 Subject: [PATCH 4/4] docs --- website/docs/r/mssql_database.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/mssql_database.html.markdown b/website/docs/r/mssql_database.html.markdown index f5c23a4ed360..0294d34f1749 100644 --- a/website/docs/r/mssql_database.html.markdown +++ b/website/docs/r/mssql_database.html.markdown @@ -220,10 +220,12 @@ The following arguments are supported: * `recover_database_id` - (Optional) The ID of the database to be recovered. This property is only applicable when the `create_mode` is `Recovery`. -* `recovery_point_id` - (Optional) The ID of the Recovery Services Recovery Point Id to be restored. This property is only applicable when the `create_mode` is `CreateModeRestoreLongTermRetentionBackup`. +* `recovery_point_id` - (Optional) The ID of the Recovery Services Recovery Point Id to be restored. This property is only applicable when the `create_mode` is `Recovery`. * `restore_dropped_database_id` - (Optional) The ID of the database to be restored. This property is only applicable when the `create_mode` is `Restore`. +* `restore_long_term_retention_backup_id` - (Optional) The ID of the long term retention backup to be restored. This property is only applicable when the `create_mode` is `RestoreLongTermRetentionBackup`. + * `read_replica_count` - (Optional) The number of readonly secondary replicas associated with the database to which readonly application intent connections may be routed. This property is only settable for Hyperscale edition databases. * `read_scale` - (Optional) If enabled, connections that have application intent set to readonly in their connection string may be routed to a readonly secondary replica. This property is only settable for Premium and Business Critical databases.