Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_backup_policy_vm - support for the tiering_policy property #26263

Merged
merged 8 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions internal/services/recoveryservices/backup_policy_vm_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func resourceBackupProtectionPolicyVMCreateUpdate(d *pluginsdk.ResourceData, met
TimeZone: utils.String(d.Get("timezone").(string)),
PolicyType: pointer.To(policyType),
SchedulePolicy: schedulePolicy,
TieringPolicy: expandBackupProtectionPolicyVMTieringPolicy(d.Get("tiering_policy").([]interface{})),
InstantRPDetails: expandBackupProtectionPolicyVMResourceGroup(d),
RetentionPolicy: &protectionpolicies.LongTermRetentionPolicy{ // SimpleRetentionPolicy only has duration property ¯\_(ツ)_/¯
DailySchedule: expandBackupProtectionPolicyVMRetentionDaily(d, times),
Expand Down Expand Up @@ -214,6 +215,7 @@ func resourceBackupProtectionPolicyVMRead(d *pluginsdk.ResourceData, meta interf
if properties, ok := model.Properties.(protectionpolicies.AzureIaaSVMProtectionPolicy); ok {
d.Set("timezone", properties.TimeZone)
d.Set("instant_restore_retention_days", properties.InstantRpRetentionRangeInDays)
d.Set("tiering_policy", flattenBackupProtectionPolicyVMTieringPolicy(properties.TieringPolicy))

if schedule, ok := properties.SchedulePolicy.(protectionpolicies.SimpleSchedulePolicy); ok {
if err := d.Set("backup", flattenBackupProtectionPolicyVMSchedule(schedule)); err != nil {
Expand Down Expand Up @@ -564,6 +566,47 @@ func expandBackupProtectionPolicyVMRetentionDailyFormat(block map[string]interfa
return &daily
}

func expandBackupProtectionPolicyVMTieringPolicy(input []interface{}) *map[string]protectionpolicies.TieringPolicy {
result := make(map[string]protectionpolicies.TieringPolicy)
if len(input) == 0 {
result["ArchivedRP"] = protectionpolicies.TieringPolicy{
TieringMode: pointer.To(protectionpolicies.TieringModeDoNotTier),
DurationType: pointer.To(protectionpolicies.RetentionDurationTypeInvalid),
Duration: pointer.To(int64(0)),
}

return &result
}

tieringPolicy := input[0].(map[string]interface{})
archivedRP := tieringPolicy["archived_rp"].([]interface{})
result["ArchivedRP"] = expandBackupProtectionPolicyVMArchivedRP(archivedRP)

return &result
}

func expandBackupProtectionPolicyVMArchivedRP(input []interface{}) protectionpolicies.TieringPolicy {
if len(input) == 0 {
return protectionpolicies.TieringPolicy{}
}

archivedRP := input[0].(map[string]interface{})

result := protectionpolicies.TieringPolicy{
TieringMode: pointer.To(protectionpolicies.TieringMode(archivedRP["tiering_mode"].(string))),
}

if v := archivedRP["duration_type"].(string); v != "" {
result.DurationType = pointer.To(protectionpolicies.RetentionDurationType(v))
}

if v := archivedRP["duration"].(int); v != 0 {
result.Duration = pointer.To(int64(v))
}

return result
}

func flattenBackupProtectionPolicyVMResourceGroup(rpDetail protectionpolicies.InstantRPAdditionalDetails) []interface{} {
if rpDetail.AzureBackupRGNamePrefix == nil {
return nil
Expand Down Expand Up @@ -769,6 +812,46 @@ func flattenBackupProtectionPolicyVMRetentionDailyFormat(retention *protectionpo
return days, includeLastDay
}

func flattenBackupProtectionPolicyVMTieringPolicy(input *map[string]protectionpolicies.TieringPolicy) []interface{} {
results := make([]interface{}, 0)
if input == nil {
return results
}

for k, v := range *input {
if k == "ArchivedRP" {
if pointer.From(v.TieringMode) == protectionpolicies.TieringModeDoNotTier && pointer.From(v.DurationType) == protectionpolicies.RetentionDurationTypeInvalid && pointer.From(v.Duration) == 0 {
return results
}

results = append(results, map[string]interface{}{
"archived_rp": flattenBackupProtectionPolicyVMArchivedRP(v),
})
}
}

return results
}

func flattenBackupProtectionPolicyVMArchivedRP(input protectionpolicies.TieringPolicy) []interface{} {
results := make([]interface{}, 0)

result := map[string]interface{}{
"tiering_mode": string(pointer.From(input.TieringMode)),
"duration": int(pointer.From(input.Duration)),
}

durationType := ""
if v := input.DurationType; v != nil && pointer.From(v) != protectionpolicies.RetentionDurationTypeInvalid {
durationType = string(pointer.From(v))
}
result["duration_type"] = durationType

results = append(results, result)

return results
}

func resourceBackupProtectionPolicyVMWaitForUpdate(ctx context.Context, client *protectionpolicies.ProtectionPoliciesClient, id protectionpolicies.BackupPolicyId, d *pluginsdk.ResourceData) error {
state := &pluginsdk.StateChangeConf{
MinTimeout: 30 * time.Second,
Expand Down Expand Up @@ -853,6 +936,51 @@ func resourceBackupProtectionPolicyVMSchema() map[string]*pluginsdk.Schema {
ValidateFunc: validate.RecoveryServicesVaultName,
},

// `tiering_policy` is defined as the map type in Swagger and currently the key only supports `ArchivedRP`. Service team confirmed that they would support other keys in the future.
"tiering_policy": {
Type: pluginsdk.TypeList,
MaxItems: 1,
Optional: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"archived_rp": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't in the docs? should it be remoed?

Copy link
Contributor Author

@neil-yechenwei neil-yechenwei Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it to md file since service team confirmed that they will support other tiers in the future.

Type: pluginsdk.TypeList,
MaxItems: 1,
Required: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"tiering_mode": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(protectionpolicies.TieringModeTierAfter),
string(protectionpolicies.TieringModeTierRecommended),
}, false),
},

"duration": {
Type: pluginsdk.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(3),
},

"duration_type": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
string(protectionpolicies.RetentionDurationTypeDays),
string(protectionpolicies.RetentionDurationTypeWeeks),
string(protectionpolicies.RetentionDurationTypeMonths),
string(protectionpolicies.RetentionDurationTypeYears),
}, false),
},
},
},
},
},
},
},

"timezone": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,21 @@ func TestAccBackupProtectionPolicyVM_completeDays(t *testing.T) {
})
}

func TestAccBackupProtectionPolicyVM_tieringPolicy(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_backup_policy_vm", "test")
r := BackupProtectionPolicyVMResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.tieringPolicy(data),
Check: acceptance.ComposeAggregateTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func (t BackupProtectionPolicyVMResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := protectionpolicies.ParseBackupPolicyID(state.ID)
if err != nil {
Expand Down Expand Up @@ -1007,3 +1022,47 @@ resource "azurerm_backup_policy_vm" "test" {
}
`, r.template(data), data.RandomInteger)
}

func (r BackupProtectionPolicyVMResource) tieringPolicy(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_backup_policy_vm" "test" {
name = "acctest-bpvm-%d"
resource_group_name = azurerm_resource_group.test.name
recovery_vault_name = azurerm_recovery_services_vault.test.name

backup {
frequency = "Weekly"
time = "23:00"
weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"]
}

retention_weekly {
count = 42
weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"]
}

retention_monthly {
count = 7
weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"]
weeks = ["First", "Last"]
}

retention_yearly {
count = 77
weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"]
weeks = ["First", "Last"]
months = ["January", "July"]
}

tiering_policy {
archived_rp {
duration = 5
duration_type = "Months"
tiering_mode = "TierAfter"
}
}
}
`, r.template(data), data.RandomInteger)
}
10 changes: 10 additions & 0 deletions website/docs/r/backup_policy_vm.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ The following arguments are supported:

* `retention_yearly` - (Optional) Configures the policy yearly retention as documented in the `retention_yearly` block below.

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

---

The `backup` block supports:
Expand Down Expand Up @@ -166,6 +168,14 @@ The `retention_yearly` block supports:

---

A `tiering_policy` block supports the following:

* `tiering_mode` - (Required) The tiering mode to control automatic tiering of recovery points. Possible values are `TierAfter` and `TierRecommended`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this can just be mode as tiering is is in the block name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it to "mode".


* `duration` - (Optional) The number of days/weeks/months/years to retain backups in current tier before tiering.

* `duration_type` - (Optional) The retention duration type. Possible values are `Days`, `Weeks`, `Months` and `Years`.

## Attributes Reference

In addition to the Arguments listed above - the following Attributes are exported:
Expand Down
Loading