Skip to content

Commit

Permalink
azurerm_mssql_managed_database - support for retention policies (#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
catriona-m authored Mar 9, 2023
1 parent a4b0c43 commit 04964a4
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 3 deletions.
10 changes: 10 additions & 0 deletions internal/services/mssql/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type Client struct {
LongTermRetentionPoliciesClient *sql.LongTermRetentionPoliciesClient
ManagedDatabasesClient *sql.ManagedDatabasesClient
ManagedInstancesClient *sql.ManagedInstancesClient
ManagedInstancesLongTermRetentionPoliciesClient *sql.ManagedInstanceLongTermRetentionPoliciesClient
ManagedInstancesShortTermRetentionPoliciesClient *sql.ManagedBackupShortTermRetentionPoliciesClient
ManagedInstanceVulnerabilityAssessmentsClient *sql.ManagedInstanceVulnerabilityAssessmentsClient
ManagedInstanceServerSecurityAlertPoliciesClient *sql.ManagedServerSecurityAlertPoliciesClient
OutboundFirewallRulesClient *sql.OutboundFirewallRulesClient
Expand Down Expand Up @@ -96,6 +98,12 @@ func NewClient(o *common.ClientOptions) *Client {
managedInstancesClient := sql.NewManagedInstancesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&managedInstancesClient.Client, o.ResourceManagerAuthorizer)

managedInstancesLongTermRetentionPoliciesClient := sql.NewManagedInstanceLongTermRetentionPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&managedInstancesLongTermRetentionPoliciesClient.Client, o.ResourceManagerAuthorizer)

managedInstancesShortTermRetentionPoliciesClient := sql.NewManagedBackupShortTermRetentionPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&managedInstancesShortTermRetentionPoliciesClient.Client, o.ResourceManagerAuthorizer)

managedInstancesAdministratorsClient := sql.NewManagedInstanceAdministratorsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&managedInstancesAdministratorsClient.Client, o.ResourceManagerAuthorizer)

Expand Down Expand Up @@ -182,7 +190,9 @@ func NewClient(o *common.ClientOptions) *Client {
ManagedInstanceAzureADOnlyAuthenticationsClient: &managedInstanceAzureADOnlyAuthenticationsClient,
ManagedInstanceEncryptionProtectorClient: &managedInstanceEncryptionProtectorsClient,
ManagedInstanceKeysClient: &managedInstanceKeysClient,
ManagedInstancesLongTermRetentionPoliciesClient: &managedInstancesLongTermRetentionPoliciesClient,
ManagedInstanceServerSecurityAlertPoliciesClient: &managedInstanceServerSecurityAlertPoliciesClient,
ManagedInstancesShortTermRetentionPoliciesClient: &managedInstancesShortTermRetentionPoliciesClient,
ManagedInstanceVulnerabilityAssessmentsClient: &managedInstanceVulnerabilityAssessmentsClient,
ManagedInstancesClient: &managedInstancesClient,
OutboundFirewallRulesClient: &outboundFirewallRulesClient,
Expand Down
173 changes: 170 additions & 3 deletions internal/services/mssql/mssql_managed_database_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,32 @@ import (
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v5.0/sql" // nolint: staticcheck
"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/helper"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/sql/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type MsSqlManagedDatabaseModel struct {
Name string `tfschema:"name"`
ManagedInstanceId string `tfschema:"managed_instance_id"`
Name string `tfschema:"name"`
ManagedInstanceId string `tfschema:"managed_instance_id"`
LongTermRetentionPolicy []LongTermRetentionPolicy `tfschema:"long_term_retention_policy"`
ShortTermRetentionDays int32 `tfschema:"short_term_retention_days"`
}

type LongTermRetentionPolicy struct {
WeeklyRetention string `tfschema:"weekly_retention"`
MonthlyRetention string `tfschema:"monthly_retention"`
YearlyRetention string `tfschema:"yearly_retention"`
WeekOfYear int32 `tfschema:"week_of_year"`
}

var _ sdk.Resource = MsSqlManagedDatabaseResource{}
var _ sdk.ResourceWithUpdate = MsSqlManagedDatabaseResource{}

type MsSqlManagedDatabaseResource struct{}

Expand Down Expand Up @@ -49,6 +62,15 @@ func (r MsSqlManagedDatabaseResource) Arguments() map[string]*pluginsdk.Schema {
ForceNew: true,
ValidateFunc: validate.ManagedInstanceID,
},

"long_term_retention_policy": helper.LongTermRetentionPolicySchema(),

"short_term_retention_days": {
Type: pluginsdk.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(1, 35),
Default: 7,
},
}
}

Expand All @@ -62,6 +84,8 @@ func (r MsSqlManagedDatabaseResource) Create() sdk.ResourceFunc {
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MSSQL.ManagedDatabasesClient
instancesClient := metadata.Client.MSSQL.ManagedInstancesClient
longTermRetentionClient := metadata.Client.MSSQL.ManagedInstancesLongTermRetentionPoliciesClient
shortTermRetentionClient := metadata.Client.MSSQL.ManagedInstancesShortTermRetentionPoliciesClient

var model MsSqlManagedDatabaseModel
if err := metadata.Decode(&model); err != nil {
Expand Down Expand Up @@ -106,18 +130,104 @@ func (r MsSqlManagedDatabaseResource) Create() sdk.ResourceFunc {
return fmt.Errorf("waiting for creation of %s: %+v", id, err)
}

if len(model.LongTermRetentionPolicy) > 0 {
longTermRetentionProps := expandLongTermRetentionPolicy(model.LongTermRetentionPolicy)

longTermRetentionPolicy := sql.ManagedInstanceLongTermRetentionPolicy{
BaseLongTermRetentionPolicyProperties: &longTermRetentionProps,
}

longTermRetentionFuture, err := longTermRetentionClient.CreateOrUpdate(ctx, id.ResourceGroup, id.ManagedInstanceName, id.DatabaseName, longTermRetentionPolicy)
if err != nil {
return fmt.Errorf("setting Long Term Retention Policies for %s: %+v", id, err)
}

if err = longTermRetentionFuture.WaitForCompletionRef(ctx, longTermRetentionClient.Client); err != nil {
return fmt.Errorf("waiting for update of Long Term Retention Policies for %s: %+v", id, err)
}
}

if model.ShortTermRetentionDays > 0 {

shortTermRetentionPolicy := sql.ManagedBackupShortTermRetentionPolicy{
ManagedBackupShortTermRetentionPolicyProperties: &sql.ManagedBackupShortTermRetentionPolicyProperties{
RetentionDays: pointer.To(model.ShortTermRetentionDays),
},
}
if _, err := shortTermRetentionClient.CreateOrUpdate(ctx, id.ResourceGroup, id.ManagedInstanceName, id.DatabaseName, shortTermRetentionPolicy); err != nil {
return fmt.Errorf("setting Short Term Retention Policy for %s: %+v", id, err)
}
}

metadata.SetID(id)

return nil
},
}
}

func (r MsSqlManagedDatabaseResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
longTermRetentionClient := metadata.Client.MSSQL.ManagedInstancesLongTermRetentionPoliciesClient
shortTermRetentionClient := metadata.Client.MSSQL.ManagedInstancesShortTermRetentionPoliciesClient

var model MsSqlManagedDatabaseModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

managedInstanceId, err := parse.ManagedInstanceID(model.ManagedInstanceId)
if err != nil {
return fmt.Errorf("parsing `managed_instance_id`: %v", err)
}

id := parse.NewManagedDatabaseID(managedInstanceId.SubscriptionId,
managedInstanceId.ResourceGroup, managedInstanceId.Name, model.Name)

d := metadata.ResourceData

if d.HasChange("long_term_retention_policy") {
longTermRetentionProps := expandLongTermRetentionPolicy(model.LongTermRetentionPolicy)

longTermRetentionPolicy := sql.ManagedInstanceLongTermRetentionPolicy{
BaseLongTermRetentionPolicyProperties: &longTermRetentionProps,
}

longTermRetentionFuture, err := longTermRetentionClient.CreateOrUpdate(ctx, id.ResourceGroup, id.ManagedInstanceName, id.DatabaseName, longTermRetentionPolicy)
if err != nil {
return fmt.Errorf("updating Long Term Retention Policies for %s: %+v", id, err)
}

if err = longTermRetentionFuture.WaitForCompletionRef(ctx, longTermRetentionClient.Client); err != nil {
return fmt.Errorf("waiting for update of Long Term Retention Policies for %s: %+v", id, err)
}
}

if d.HasChange("short_term_retention_days") {

shortTermRetentionPolicy := sql.ManagedBackupShortTermRetentionPolicy{
ManagedBackupShortTermRetentionPolicyProperties: &sql.ManagedBackupShortTermRetentionPolicyProperties{
RetentionDays: pointer.To(model.ShortTermRetentionDays),
},
}
if _, err := shortTermRetentionClient.CreateOrUpdate(ctx, id.ResourceGroup, id.ManagedInstanceName, id.DatabaseName, shortTermRetentionPolicy); err != nil {
return fmt.Errorf("updating Short Term Retention Policy for %s: %+v", id, err)
}
}
return nil
},
}
}

func (r MsSqlManagedDatabaseResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MSSQL.ManagedDatabasesClient
longTermRetentionClient := metadata.Client.MSSQL.ManagedInstancesLongTermRetentionPoliciesClient
shortTermRetentionClient := metadata.Client.MSSQL.ManagedInstancesShortTermRetentionPoliciesClient

id, err := parse.ManagedDatabaseID(metadata.ResourceData.Id())
if err != nil {
Expand All @@ -135,7 +245,7 @@ func (r MsSqlManagedDatabaseResource) Read() sdk.ResourceFunc {
if utils.ResponseWasNotFound(result.Response) {
return metadata.MarkAsGone(id)
}
return fmt.Errorf("retrieving %s: %v", id, err)
return fmt.Errorf("retrieving %s: %v", *id, err)
}

managedInstanceId := parse.NewManagedInstanceID(id.SubscriptionId, id.ResourceGroup, id.ManagedInstanceName)
Expand All @@ -145,6 +255,22 @@ func (r MsSqlManagedDatabaseResource) Read() sdk.ResourceFunc {
ManagedInstanceId: managedInstanceId.ID(),
}

ltrResp, err := longTermRetentionClient.Get(ctx, id.ResourceGroup, id.ManagedInstanceName, id.DatabaseName)
if err != nil {
return fmt.Errorf("retrieving Long Term Retention Policy for %s: %v", *id, err)
}

model.LongTermRetentionPolicy = flattenLongTermRetentionPolicy(ltrResp)

shortTermRetentionResp, err := shortTermRetentionClient.Get(ctx, id.ResourceGroup, id.ManagedInstanceName, id.DatabaseName)
if err != nil {
return fmt.Errorf("retrieving Short Term Retention Policy for %s: %v", *id, err)
}

if shortTermRetentionResp.RetentionDays != nil {
model.ShortTermRetentionDays = *shortTermRetentionResp.RetentionDays
}

return metadata.Encode(&model)
},
}
Expand Down Expand Up @@ -174,3 +300,44 @@ func (r MsSqlManagedDatabaseResource) Delete() sdk.ResourceFunc {
},
}
}

func expandLongTermRetentionPolicy(ltrPolicy []LongTermRetentionPolicy) sql.BaseLongTermRetentionPolicyProperties {
return sql.BaseLongTermRetentionPolicyProperties{
WeeklyRetention: &ltrPolicy[0].WeeklyRetention,
MonthlyRetention: &ltrPolicy[0].MonthlyRetention,
YearlyRetention: &ltrPolicy[0].YearlyRetention,
WeekOfYear: &ltrPolicy[0].WeekOfYear,
}
}

func flattenLongTermRetentionPolicy(ltrPolicy sql.ManagedInstanceLongTermRetentionPolicy) []LongTermRetentionPolicy {

ltrModel := LongTermRetentionPolicy{}

weeklyRetention := ""
if ltrPolicy.WeeklyRetention != nil {
weeklyRetention = *ltrPolicy.WeeklyRetention
}

monthlyRetention := ""
if ltrPolicy.MonthlyRetention != nil {
monthlyRetention = *ltrPolicy.MonthlyRetention
}

yearlyRetention := ""
if ltrPolicy.YearlyRetention != nil {
yearlyRetention = *ltrPolicy.YearlyRetention
}

ltrModel = LongTermRetentionPolicy{
WeeklyRetention: weeklyRetention,
MonthlyRetention: monthlyRetention,
YearlyRetention: yearlyRetention,
}

if ltrPolicy.WeekOfYear != nil {
ltrModel.WeekOfYear = *ltrPolicy.WeekOfYear
}

return []LongTermRetentionPolicy{ltrModel}
}
63 changes: 63 additions & 0 deletions internal/services/mssql/mssql_managed_database_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ func TestAccMsSqlManagedDatabase_basic(t *testing.T) {
})
}

func TestAccMsSqlManagedDatabase_withRetentionPolicies(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_managed_database", "test")
r := MsSqlManagedDatabase{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.withRetentionPolicies(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(""),
{
Config: r.withRetentionPoliciesUpdated(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
})
}

func (r MsSqlManagedDatabase) Exists(ctx context.Context, client *clients.Client, state *acceptance.InstanceState) (*bool, error) {
id, err := parse.ManagedDatabaseID(state.ID)
if err != nil {
Expand Down Expand Up @@ -56,3 +77,45 @@ resource "azurerm_mssql_managed_database" "test" {
}
`, MsSqlManagedInstanceResource{}.basic(data), data.RandomInteger)
}

func (r MsSqlManagedDatabase) withRetentionPolicies(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
resource "azurerm_mssql_managed_database" "test" {
managed_instance_id = azurerm_mssql_managed_instance.test.id
name = "acctest-%[2]d"
long_term_retention_policy {
weekly_retention = "P1W"
monthly_retention = "P1M"
yearly_retention = "P1Y"
week_of_year = 1
}
short_term_retention_days = 3
}
`, MsSqlManagedInstanceResource{}.basic(data), data.RandomInteger)
}

func (r MsSqlManagedDatabase) withRetentionPoliciesUpdated(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
resource "azurerm_mssql_managed_database" "test" {
managed_instance_id = azurerm_mssql_managed_instance.test.id
name = "acctest-%[2]d"
long_term_retention_policy {
weekly_retention = "P10D"
monthly_retention = "P1M"
yearly_retention = "P1Y"
week_of_year = 4
}
short_term_retention_days = 4
}
`, MsSqlManagedInstanceResource{}.basic(data), data.RandomInteger)
}
14 changes: 14 additions & 0 deletions website/docs/r/mssql_managed_database.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,21 @@ The following arguments are supported:

* `managed_instance_id` - (Required) The ID of the Azure SQL Managed Instance on which to create this Managed Database. Changing this forces a new resource to be created.

* `long_term_retention_policy` - (Optional) A `long_term_retention_policy` block as defined below.

* `short_term_retention_days` - (Optional) The backup retention period in days. This is how many days Point-in-Time Restore will be supported.

---

A `long_term_retention_policy` block supports the following:

* `weekly_retention` - (Optional) The weekly retention policy for an LTR backup in an ISO 8601 format. Valid value is between 1 to 520 weeks. e.g. `P1Y`, `P1M`, `P1W` or `P7D`.
* `monthly_retention` - (Optional) The monthly retention policy for an LTR backup in an ISO 8601 format. Valid value is between 1 to 120 months. e.g. `P1Y`, `P1M`, `P4W` or `P30D`.
* `yearly_retention` - (Optional) The yearly retention policy for an LTR backup in an ISO 8601 format. Valid value is between 1 to 10 years. e.g. `P1Y`, `P12M`, `P52W` or `P365D`.
* `week_of_year` - (Optional) The week of year to take the yearly backup. Value has to be between `1` and `52`.

## Attributes Reference

The following attributes are exported:

* `id` - The Azure SQL Managed Database ID.
Expand All @@ -73,6 +86,7 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/l

* `read` - (Defaults to 5 minutes) Used when retrieving the Mssql Managed Database.
* `create` - (Defaults to 30 minutes) Used when creating the Mssql Managed Database.
* `update` - (Defaults to 30 minutes) Used when updating the Mssql Managed Database.
* `delete` - (Defaults to 30 minutes) Used when deleting the Mssql Managed Database.

## Import
Expand Down

0 comments on commit 04964a4

Please sign in to comment.