From 35a5014500ec326b3d95a19dd3f064348ef46897 Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Wed, 27 Dec 2023 18:06:27 +0800 Subject: [PATCH 1/9] support target_copy_setting property --- ...ction_backup_policy_postgresql_resource.go | 396 ++++++++++++++++-- ..._backup_policy_postgresql_resource_test.go | 250 +++++++++-- 2 files changed, 592 insertions(+), 54 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go index f8d7c197dae0..1aa956ae9d0a 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go @@ -4,6 +4,7 @@ package dataprotection import ( + "encoding/json" "fmt" "log" "regexp" @@ -17,6 +18,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" @@ -24,7 +26,7 @@ import ( ) func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { - return &pluginsdk.Resource{ + resource := &pluginsdk.Resource{ Create: resourceDataProtectionBackupPolicyPostgreSQLCreate, Read: resourceDataProtectionBackupPolicyPostgreSQLRead, Delete: resourceDataProtectionBackupPolicyPostgreSQLDelete, @@ -69,13 +71,6 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, }, - "default_retention_duration": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ISO8601Duration, - }, - "retention_rule": { Type: pluginsdk.TypeList, Optional: true, @@ -88,13 +83,6 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ForceNew: true, }, - "duration": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ISO8601Duration, - }, - "criteria": { Type: pluginsdk.TypeList, Required: true, @@ -185,6 +173,146 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, }, } + + if !features.FourPointOhBeta() { + // remove 'default_retention_duration' in tf 4.0 is replaced by `default_retention_rule.0.life_cycle.#.duration` + resource.Schema["default_retention_duration"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + } + // remove 'duration' in tf 4.0 is replaced by `retention_rule.#.life_cycle.#.duration` + resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["duration"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + } + } else { + // Add `life_cycle` in tf 4.0 since `retention_rule.#.life_cycle.#.target_copy_setting` and `retention_rule.#.life_cycle.#.data_store_type` should be specified by user and are not fixed. + resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // confirmed with the service team that the possible values do not include `OperationalStore`. + string(backuppolicies.DataStoreTypesVaultStore), + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + + "duration": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + }, + + "target_copy_setting": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "copy_after": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsJSON, + }, + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // since the following feedback from the service team, the current possible values only support `ArchiveStore`. + // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + }, + }, + }, + }, + }, + } + + // Add `default_retention_rule` in tf 4.0 since `default_retention_rule.0.data_store_type` and `default_retention_rule.0.target_copy_setting` should be specified by user and are not fixed. + resource.Schema["default_retention_rule"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "life_cycle": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // confirmed with the service team that the possible values do not include `OperationalStore`. + string(backuppolicies.DataStoreTypesVaultStore), + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + + "duration": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + }, + + "target_copy_setting": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "copy_after": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsJSON, + }, + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // since the following feedback from the service team, the current possible values only support `ArchiveStore`. + // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + } + return resource } func resourceDataProtectionBackupPolicyPostgreSQLCreate(d *pluginsdk.ResourceData, meta interface{}) error { @@ -216,8 +344,15 @@ func resourceDataProtectionBackupPolicyPostgreSQLCreate(d *pluginsdk.ResourceDat policyRules := make([]backuppolicies.BasePolicyRule, 0) policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureBackupRuleArray(d.Get("backup_repeating_time_intervals").([]interface{}), d.Get("time_zone").(string), taggingCriteria)...) - policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(d.Get("default_retention_duration"))) - policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRuleArray(d.Get("retention_rule").([]interface{}))...) + + if !features.FourPointOhBeta() { + policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(d.Get("default_retention_duration"))) + policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRuleArray(d.Get("retention_rule").([]interface{}))...) + } else { + policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultRetentionRule(d.Get("default_retention_rule").([]interface{}))) + policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRules(d.Get("retention_rule").([]interface{}))...) + } + parameters := backuppolicies.BaseBackupPolicyResource{ Properties: &backuppolicies.BackupPolicy{ PolicyRules: policyRules, @@ -262,12 +397,23 @@ func resourceDataProtectionBackupPolicyPostgreSQLRead(d *pluginsdk.ResourceData, if err := d.Set("backup_repeating_time_intervals", flattenBackupPolicyPostgreSQLBackupRuleArray(&props.PolicyRules)); err != nil { return fmt.Errorf("setting `backup_rule`: %+v", err) } - if err := d.Set("default_retention_duration", flattenBackupPolicyPostgreSQLDefaultRetentionRuleDuration(&props.PolicyRules)); err != nil { - return fmt.Errorf("setting `default_retention_duration`: %+v", err) - } - if err := d.Set("retention_rule", flattenBackupPolicyPostgreSQLRetentionRuleArray(&props.PolicyRules)); err != nil { - return fmt.Errorf("setting `retention_rule`: %+v", err) + + if !features.FourPointOhBeta() { + if err := d.Set("default_retention_duration", flattenBackupPolicyPostgreSQLDefaultRetentionRuleDuration(&props.PolicyRules)); err != nil { + return fmt.Errorf("setting `default_retention_duration`: %+v", err) + } + if err := d.Set("retention_rule", flattenBackupPolicyPostgreSQLRetentionRuleArray(&props.PolicyRules)); err != nil { + return fmt.Errorf("setting `retention_rule`: %+v", err) + } + } else { + if err := d.Set("default_retention_rule", flattenBackupPolicyPostgreSQLDefaultRetentionRule(&props.PolicyRules)); err != nil { + return fmt.Errorf("setting `default_retention_rule`: %+v", err) + } + if err := d.Set("retention_rule", flattenBackupPolicyPostgreSQLRetentionRules(&props.PolicyRules)); err != nil { + return fmt.Errorf("setting `retention_rule`: %+v", err) + } } + d.Set("time_zone", flattenBackupPolicyPostgreSQLBackupTimeZone(&props.PolicyRules)) } } @@ -342,6 +488,21 @@ func expandBackupPolicyPostgreSQLAzureRetentionRuleArray(input []interface{}) [] return results } +func expandBackupPolicyPostgreSQLAzureRetentionRules(input []interface{}) []backuppolicies.BasePolicyRule { + results := make([]backuppolicies.BasePolicyRule, 0) + for _, item := range input { + v := item.(map[string]interface{}) + lifeCycle := expandBackupPolicyPostgreSQLLifeCycle(v["life_cycle"].([]interface{})) + + results = append(results, backuppolicies.AzureRetentionRule{ + Name: v["name"].(string), + IsDefault: pointer.To(false), + Lifecycles: lifeCycle, + }) + } + return results +} + func expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(input interface{}) backuppolicies.BasePolicyRule { return backuppolicies.AzureRetentionRule{ Name: "Default", @@ -361,9 +522,79 @@ func expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(input interface{}) ba } } +func expandBackupPolicyPostgreSQLDefaultRetentionRule(input []interface{}) backuppolicies.BasePolicyRule { + results := backuppolicies.AzureRetentionRule{} + for _, item := range input { + v := item.(map[string]interface{}) + + lifeCycle := expandBackupPolicyPostgreSQLLifeCycle(v["life_cycle"].([]interface{})) + results.Name = "Default" + results.IsDefault = pointer.To(true) + results.Lifecycles = lifeCycle + } + return results +} + +func expandBackupPolicyPostgreSQLLifeCycle(input []interface{}) []backuppolicies.SourceLifeCycle { + results := make([]backuppolicies.SourceLifeCycle, 0) + for _, item := range input { + v := item.(map[string]interface{}) + targetCopySettingList := make([]backuppolicies.TargetCopySetting, 0) + if tcs := v["target_copy_setting"].([]interface{}); len(tcs) > 0 { + tcsv := tcs[0].(map[string]interface{}) + copyAfter, err := expandTargetCopySettingFromJSON(tcsv["copy_after"].(string)) + if err != nil { + return results + } + + targetCopySetting := backuppolicies.TargetCopySetting{ + CopyAfter: copyAfter, + DataStore: backuppolicies.DataStoreInfoBase{ + DataStoreType: backuppolicies.DataStoreTypes(tcsv["data_store_type"].(string)), + ObjectType: "DataStoreInfoBase", + }, + } + targetCopySettingList = append(targetCopySettingList, targetCopySetting) + } + + sourceLifeCycle := backuppolicies.SourceLifeCycle{ + DeleteAfter: backuppolicies.AbsoluteDeleteOption{ + Duration: v["duration"].(string), + }, + SourceDataStore: backuppolicies.DataStoreInfoBase{ + DataStoreType: backuppolicies.DataStoreTypes(v["data_store_type"].(string)), + ObjectType: "DataStoreInfoBase", + }, + TargetDataStoreCopySettings: pointer.To(targetCopySettingList), + } + results = append(results, sourceLifeCycle) + } + + return results +} + +func expandTargetCopySettingFromJSON(input string) (backuppolicies.CopyOption, error) { + if input == "" { + return nil, nil + } + targetCopySetting := &backuppolicies.TargetCopySetting{} + err := targetCopySetting.UnmarshalJSON([]byte(fmt.Sprintf(`{ "copyAfter": %s }`, input))) + if err != nil { + return nil, err + } + return targetCopySetting.CopyAfter, nil +} + +func flattenTargetCopySettingFromJSON(input backuppolicies.CopyOption) (string, error) { + if input == nil { + return "", nil + } + result, err := json.Marshal(input) + return string(result), err +} + func expandBackupPolicyPostgreSQLTaggingCriteriaArray(input []interface{}) (*[]backuppolicies.TaggingCriteria, error) { results := []backuppolicies.TaggingCriteria{ - { Criteria: nil, IsDefault: true, @@ -390,7 +621,6 @@ func expandBackupPolicyPostgreSQLTaggingCriteriaArray(input []interface{}) (*[]b return nil, err } result.Criteria = criteria - results = append(results, result) } return &results, nil @@ -400,6 +630,7 @@ func expandBackupPolicyPostgreSQLCriteriaArray(input []interface{}) (*[]backuppo if len(input) == 0 || input[0] == nil { return nil, fmt.Errorf("criteria is a required field, cannot leave blank") } + results := make([]backuppolicies.BackupCriteria, 0) for _, item := range input { @@ -543,6 +774,75 @@ func flattenBackupPolicyPostgreSQLRetentionRuleArray(input *[]backuppolicies.Bas return results } +func flattenBackupPolicyPostgreSQLRetentionRules(input *[]backuppolicies.BasePolicyRule) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + var taggingCriterias []backuppolicies.TaggingCriteria + for _, item := range *input { + if backupRule, ok := item.(backuppolicies.AzureBackupRule); ok { + if trigger, ok := backupRule.Trigger.(backuppolicies.ScheduleBasedTriggerContext); ok { + if trigger.TaggingCriteria != nil { + taggingCriterias = trigger.TaggingCriteria + } + } + } + } + + for _, item := range *input { + if retentionRule, ok := item.(backuppolicies.AzureRetentionRule); ok { + var name string + var taggingPriority int64 + var taggingCriteria []interface{} + if retentionRule.IsDefault == nil || !*retentionRule.IsDefault { + name = retentionRule.Name + for _, criteria := range taggingCriterias { + if strings.EqualFold(criteria.TagInfo.TagName, name) { + taggingPriority = criteria.TaggingPriority + taggingCriteria = flattenBackupPolicyPostgreSQLBackupCriteriaArray(criteria.Criteria) + } + } + + var lifeCycle []interface{} + if v := retentionRule.Lifecycles; len(v) > 0 { + lifeCycle = flattenBackupPolicyPostgreSQLBackupLifeCycleArray(v) + } + results = append(results, map[string]interface{}{ + "name": name, + "priority": taggingPriority, + "criteria": taggingCriteria, + "life_cycle": lifeCycle, + }) + } + } + } + return results +} + +func flattenBackupPolicyPostgreSQLDefaultRetentionRule(input *[]backuppolicies.BasePolicyRule) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range *input { + if retentionRule, ok := item.(backuppolicies.AzureRetentionRule); ok { + if pointer.From(retentionRule.IsDefault) { + var lifeCycle []interface{} + if v := retentionRule.Lifecycles; len(v) > 0 { + lifeCycle = flattenBackupPolicyPostgreSQLBackupLifeCycleArray(v) + } + results = append(results, map[string]interface{}{ + "life_cycle": lifeCycle, + }) + } + } + } + return results +} + func flattenBackupPolicyPostgreSQLBackupCriteriaArray(input *[]backuppolicies.BackupCriteria) []interface{} { results := make([]interface{}, 0) if input == nil { @@ -593,3 +893,51 @@ func flattenBackupPolicyPostgreSQLBackupCriteriaArray(input *[]backuppolicies.Ba } return results } + +func flattenBackupPolicyPostgreSQLBackupLifeCycleArray(input []backuppolicies.SourceLifeCycle) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } + + for _, item := range input { + var targetDataStoreCopySetting []interface{} + var duration string + var dataStoreType string + if v := item.TargetDataStoreCopySettings; v != nil && len(*v) > 0 { + targetDataStoreCopySetting = flattenBackupPolicyPostgreSQLBackupTargetDataStoreCopySettingArray(v) + } + if deleteOption, ok := item.DeleteAfter.(backuppolicies.AbsoluteDeleteOption); ok { + duration = deleteOption.Duration + } + dataStoreType = string(item.SourceDataStore.DataStoreType) + + results = append(results, map[string]interface{}{ + "duration": duration, + "target_copy_setting": targetDataStoreCopySetting, + "data_store_type": dataStoreType, + }) + } + return results +} + +func flattenBackupPolicyPostgreSQLBackupTargetDataStoreCopySettingArray(input *[]backuppolicies.TargetCopySetting) []interface{} { + results := make([]interface{}, 0) + if input == nil || len(*input) == 0 { + return results + } + + for _, item := range *input { + copyAfter, err := flattenTargetCopySettingFromJSON(item.CopyAfter) + if err != nil { + return nil + } + dataStoreType := string(item.DataStore.DataStoreType) + + results = append(results, map[string]interface{}{ + "copy_after": copyAfter, + "data_store_type": dataStoreType, + }) + } + return results +} diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index e3793089be40..50e3fbdbd087 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" ) @@ -22,43 +23,133 @@ type DataProtectionBackupPolicyPostgreSQLResource struct{} func TestAccDataProtectionBackupPolicyPostgreSQL_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) + if !features.FourPointOhBeta() { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicV3(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) + } else { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) + } } func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImport(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.RequiresImportErrorStep(r.requiresImport), - }) + if !features.FourPointOhBeta() { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicV3(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImportV3), + }) + } else { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) + } } func TestAccDataProtectionBackupPolicyPostgreSQL_complete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.complete(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) + if !features.FourPointOhBeta() { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeV3(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) + } else { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) + } +} + +func TestAccDataProtectionBackupPolicyPostgreSQL_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") + r := DataProtectionBackupPolicyPostgreSQLResource{} + if !features.FourPointOhBeta() { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicV3(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.completeV3(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basicV3(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) + } else { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) + } } func (r DataProtectionBackupPolicyPostgreSQLResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { @@ -97,7 +188,7 @@ resource "azurerm_data_protection_backup_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) basic(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) basicV3(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` %s @@ -113,6 +204,44 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { `, template, data.RandomInteger) } +func (r DataProtectionBackupPolicyPostgreSQLResource) basic(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_data_protection_backup_policy_postgresql" "test" { + name = "acctest-dbp-%d" + resource_group_name = azurerm_resource_group.test.name + vault_name = azurerm_data_protection_backup_vault.test.name + + backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"] + + default_retention_rule { + life_cycle { + duration = "P4M" + data_store_type = "VaultStore" + } + } +} +`, template, data.RandomInteger) +} + +func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImportV3(data acceptance.TestData) string { + config := r.basicV3(data) + return fmt.Sprintf(` +%s + +resource "azurerm_data_protection_backup_policy_postgresql" "import" { + name = azurerm_data_protection_backup_policy_postgresql.test.name + resource_group_name = azurerm_data_protection_backup_policy_postgresql.test.resource_group_name + vault_name = azurerm_data_protection_backup_policy_postgresql.test.vault_name + + backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"] + default_retention_duration = "P4M" +} +`, config) +} + func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImport(data acceptance.TestData) string { config := r.basic(data) return fmt.Sprintf(` @@ -124,12 +253,18 @@ resource "azurerm_data_protection_backup_policy_postgresql" "import" { vault_name = azurerm_data_protection_backup_policy_postgresql.test.vault_name backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"] - default_retention_duration = "P4M" + + default_retention_rule { + life_cycle { + duration = "P4M" + data_store_type = "VaultStore" + } + } } `, config) } -func (r DataProtectionBackupPolicyPostgreSQLResource) complete(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) completeV3(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` %s @@ -176,3 +311,58 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { } `, template, data.RandomInteger) } + +func (r DataProtectionBackupPolicyPostgreSQLResource) complete(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_data_protection_backup_policy_postgresql" "test" { + name = "acctest-dbp-%d" + resource_group_name = azurerm_resource_group.test.name + vault_name = azurerm_data_protection_backup_vault.test.name + backup_repeating_time_intervals = ["R/2023-12-31T10:00:00+05:30/P1W"] + + retention_rule { + name = "Weekly" + priority = 30 + life_cycle { + duration = "P12W" + data_store_type = "VaultStore" + target_copy_setting { + copy_after = jsonencode({ + objectType = "CopyOnExpiryOption" + }) + data_store_type = "ArchiveStore" + } + } + life_cycle { + duration = "P27W" + data_store_type = "ArchiveStore" + } + criteria { + weeks_of_month = ["First", "Last"] + days_of_week = ["Tuesday"] + scheduled_backup_times = ["2021-05-23T02:30:00Z"] + } + } + + default_retention_rule { + life_cycle { + duration = "P12M" + data_store_type = "VaultStore" + target_copy_setting { + copy_after = jsonencode({ + objectType = "CopyOnExpiryOption" + }) + data_store_type = "ArchiveStore" + } + } + life_cycle { + duration = "P27M" + data_store_type = "ArchiveStore" + } + } +} +`, template, data.RandomInteger) +} From 89fcd790f0724c1ddaccb76bcc562e4b36bdfb47 Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Sat, 17 Feb 2024 16:47:39 +0800 Subject: [PATCH 2/9] update code --- .../data_protection_backup_policy_postgresql_resource.go | 8 ++++---- ...a_protection_backup_policy_postgresql_resource_test.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go index 1aa956ae9d0a..d070a20b62e8 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go @@ -222,7 +222,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "copy_after": { + "copy_option": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -285,7 +285,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "copy_after": { + "copy_option": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -542,7 +542,7 @@ func expandBackupPolicyPostgreSQLLifeCycle(input []interface{}) []backuppolicies targetCopySettingList := make([]backuppolicies.TargetCopySetting, 0) if tcs := v["target_copy_setting"].([]interface{}); len(tcs) > 0 { tcsv := tcs[0].(map[string]interface{}) - copyAfter, err := expandTargetCopySettingFromJSON(tcsv["copy_after"].(string)) + copyAfter, err := expandTargetCopySettingFromJSON(tcsv["copy_option"].(string)) if err != nil { return results } @@ -935,7 +935,7 @@ func flattenBackupPolicyPostgreSQLBackupTargetDataStoreCopySettingArray(input *[ dataStoreType := string(item.DataStore.DataStoreType) results = append(results, map[string]interface{}{ - "copy_after": copyAfter, + "copy_option": copyAfter, "data_store_type": dataStoreType, }) } diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index 50e3fbdbd087..d57d2b2f835a 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -330,7 +330,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { duration = "P12W" data_store_type = "VaultStore" target_copy_setting { - copy_after = jsonencode({ + copy_option = jsonencode({ objectType = "CopyOnExpiryOption" }) data_store_type = "ArchiveStore" @@ -352,7 +352,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { duration = "P12M" data_store_type = "VaultStore" target_copy_setting { - copy_after = jsonencode({ + copy_option = jsonencode({ objectType = "CopyOnExpiryOption" }) data_store_type = "ArchiveStore" From b120c023b52fd304c54f884cb5a798a7ae770acc Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Thu, 7 Mar 2024 11:56:02 +0800 Subject: [PATCH 3/9] update code --- ...ction_backup_policy_postgresql_resource.go | 164 ++++++++- ..._backup_policy_postgresql_resource_test.go | 312 +++++++++++------- ...ion_backup_policy_postgresql.html.markdown | 38 ++- 3 files changed, 384 insertions(+), 130 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go index d070a20b62e8..b7b257ca6e60 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go @@ -4,10 +4,12 @@ package dataprotection import ( + "context" "encoding/json" "fmt" "log" "regexp" + "strconv" "strings" "time" @@ -172,25 +174,169 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ValidateFunc: validation.StringIsNotEmpty, }, }, + + CustomizeDiff: pluginsdk.CustomizeDiffShim(func(ctx context.Context, diff *pluginsdk.ResourceDiff, v interface{}) error { + if !features.FourPointOhBeta() { + retentionRules := diff.Get("retention_rule") + defaultRetentionDuration := diff.Get("default_retention_duration") + defaultRetentionRule := diff.Get("default_retention_rule") + + for i, rule := range retentionRules.([]interface{}) { + v := rule.(map[string]interface{}) + if v["duration"].(string) == "" && len(v["life_cycle"].([]interface{})) == 0 || v["duration"].(string) != "" && len(v["life_cycle"].([]interface{})) > 0 { + return fmt.Errorf(`one of "retention_rule.%s.duration", "retention_rule.%s.life_cycle" must be specified`, strconv.Itoa(i), strconv.Itoa(i)) + } + + if defaultRetentionDuration != "" && v["duration"].(string) == "" { + return fmt.Errorf(`"default_retention_duration", "retention_rule.%s.duration" must be specified at the same time`, strconv.Itoa(i)) + } + + if len(defaultRetentionRule.([]interface{})) > 0 && len(v["life_cycle"].([]interface{})) == 0 { + return fmt.Errorf(`"default_retention_rule", "retention_rule.%s.life_cycle" must be specified at the same time`, strconv.Itoa(i)) + } + } + } + return nil + }), } if !features.FourPointOhBeta() { - // remove 'default_retention_duration' in tf 4.0 is replaced by `default_retention_rule.0.life_cycle.#.duration` resource.Schema["default_retention_duration"] = &pluginsdk.Schema{ Type: pluginsdk.TypeString, - Required: true, + Optional: true, ForceNew: true, + ExactlyOneOf: []string{"default_retention_duration", "default_retention_rule"}, + Deprecated: "`default_retention_duration` should be removed in favour of the `default_retention_rule.0.life_cycle.#.duration` property in version 4.0 of the AzureRM Provider.", ValidateFunc: validate.ISO8601Duration, } - // remove 'duration' in tf 4.0 is replaced by `retention_rule.#.life_cycle.#.duration` resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["duration"] = &pluginsdk.Schema{ Type: pluginsdk.TypeString, - Required: true, + Optional: true, ForceNew: true, + Deprecated: "`retention_rule.#.duration` should be removed in favour of the `retention_rule.#.life_cycle.#.duration` property in version 4.0 of the AzureRM Provider.", ValidateFunc: validate.ISO8601Duration, } + resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // confirmed with the service team that the possible values do not include `OperationalStore`. + string(backuppolicies.DataStoreTypesVaultStore), + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + + "duration": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + }, + + "target_copy_setting": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "copy_option": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsJSON, + }, + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // since the following feedback from the service team, the current possible values only support `ArchiveStore`. + // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + }, + }, + }, + }, + }, + } + + resource.Schema["default_retention_rule"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + ExactlyOneOf: []string{"default_retention_duration", "default_retention_rule"}, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "life_cycle": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // confirmed with the service team that the possible values do not include `OperationalStore`. + string(backuppolicies.DataStoreTypesVaultStore), + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + + "duration": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + }, + + "target_copy_setting": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "copy_option": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsJSON, + }, + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // since the following feedback from the service team, the current possible values only support `ArchiveStore`. + // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } } else { - // Add `life_cycle` in tf 4.0 since `retention_rule.#.life_cycle.#.target_copy_setting` and `retention_rule.#.life_cycle.#.data_store_type` should be specified by user and are not fixed. resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"] = &pluginsdk.Schema{ Type: pluginsdk.TypeList, Required: true, @@ -246,7 +392,6 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, } - // Add `default_retention_rule` in tf 4.0 since `default_retention_rule.0.data_store_type` and `default_retention_rule.0.target_copy_setting` should be specified by user and are not fixed. resource.Schema["default_retention_rule"] = &pluginsdk.Schema{ Type: pluginsdk.TypeList, Required: true, @@ -312,6 +457,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, } } + return resource } @@ -345,8 +491,8 @@ func resourceDataProtectionBackupPolicyPostgreSQLCreate(d *pluginsdk.ResourceDat policyRules := make([]backuppolicies.BasePolicyRule, 0) policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureBackupRuleArray(d.Get("backup_repeating_time_intervals").([]interface{}), d.Get("time_zone").(string), taggingCriteria)...) - if !features.FourPointOhBeta() { - policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(d.Get("default_retention_duration"))) + if v, ok := d.GetOk("default_retention_duration"); ok && !features.FourPointOhBeta() { + policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(v)) policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRuleArray(d.Get("retention_rule").([]interface{}))...) } else { policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultRetentionRule(d.Get("default_retention_rule").([]interface{}))) @@ -398,7 +544,7 @@ func resourceDataProtectionBackupPolicyPostgreSQLRead(d *pluginsdk.ResourceData, return fmt.Errorf("setting `backup_rule`: %+v", err) } - if !features.FourPointOhBeta() { + if _, ok := d.GetOk("default_retention_duration"); ok && !features.FourPointOhBeta() { if err := d.Set("default_retention_duration", flattenBackupPolicyPostgreSQLDefaultRetentionRuleDuration(&props.PolicyRules)); err != nil { return fmt.Errorf("setting `default_retention_duration`: %+v", err) } diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index d57d2b2f835a..cd3247712de4 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -13,143 +13,220 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" ) type DataProtectionBackupPolicyPostgreSQLResource struct{} +func TestAccDataProtectionBackupPolicyPostgreSQL_basicDeprecatedInV4(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") + r := DataProtectionBackupPolicyPostgreSQLResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicDeprecatedInV4(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", + ), + }) +} + func TestAccDataProtectionBackupPolicyPostgreSQL_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - if !features.FourPointOhBeta() { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basicV3(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) - } else { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) - } + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImportDeprecatedInV4(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") + r := DataProtectionBackupPolicyPostgreSQLResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicDeprecatedInV4(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImportDeprecatedInV4), + }) } func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImport(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - if !features.FourPointOhBeta() { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basicV3(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.RequiresImportErrorStep(r.requiresImportV3), - }) - } else { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.RequiresImportErrorStep(r.requiresImport), - }) - } + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccDataProtectionBackupPolicyPostgreSQL_completeDeprecatedInV4(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") + r := DataProtectionBackupPolicyPostgreSQLResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeDeprecatedInV4(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", + "retention_rule.0.duration", + "retention_rule.0.life_cycle.#", + "retention_rule.0.life_cycle.0.%", + "retention_rule.0.life_cycle.0.data_store_type", + "retention_rule.0.life_cycle.0.duration", + "retention_rule.1.duration", + "retention_rule.1.life_cycle.#", + "retention_rule.1.life_cycle.0.%", + "retention_rule.1.life_cycle.0.data_store_type", + "retention_rule.1.life_cycle.0.duration", + "retention_rule.2.duration", + "retention_rule.2.life_cycle.#", + "retention_rule.2.life_cycle.0.%", + "retention_rule.2.life_cycle.0.data_store_type", + "retention_rule.2.life_cycle.0.duration", + ), + }) } func TestAccDataProtectionBackupPolicyPostgreSQL_complete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - if !features.FourPointOhBeta() { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.completeV3(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) - } else { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.complete(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) - } + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccDataProtectionBackupPolicyPostgreSQL_updateDeprecatedInV4(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") + r := DataProtectionBackupPolicyPostgreSQLResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basicDeprecatedInV4(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", + ), + { + Config: r.completeDeprecatedInV4(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", + "retention_rule.0.duration", + "retention_rule.0.life_cycle.#", + "retention_rule.0.life_cycle.0.%", + "retention_rule.0.life_cycle.0.data_store_type", + "retention_rule.0.life_cycle.0.duration", + "retention_rule.1.duration", + "retention_rule.1.life_cycle.#", + "retention_rule.1.life_cycle.0.%", + "retention_rule.1.life_cycle.0.data_store_type", + "retention_rule.1.life_cycle.0.duration", + "retention_rule.2.duration", + "retention_rule.2.life_cycle.#", + "retention_rule.2.life_cycle.0.%", + "retention_rule.2.life_cycle.0.data_store_type", + "retention_rule.2.life_cycle.0.duration", + ), + { + Config: r.basicDeprecatedInV4(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", + ), + }) } func TestAccDataProtectionBackupPolicyPostgreSQL_update(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - if !features.FourPointOhBeta() { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basicV3(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - { - Config: r.completeV3(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - { - Config: r.basicV3(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) - } else { - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - { - Config: r.complete(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) - } + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) } func (r DataProtectionBackupPolicyPostgreSQLResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { @@ -188,7 +265,7 @@ resource "azurerm_data_protection_backup_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) basicV3(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) basicDeprecatedInV4(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` %s @@ -226,8 +303,8 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { `, template, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImportV3(data acceptance.TestData) string { - config := r.basicV3(data) +func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImportDeprecatedInV4(data acceptance.TestData) string { + config := r.basicDeprecatedInV4(data) return fmt.Sprintf(` %s @@ -264,7 +341,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "import" { `, config) } -func (r DataProtectionBackupPolicyPostgreSQLResource) completeV3(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) completeDeprecatedInV4(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` %s @@ -346,7 +423,6 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { scheduled_backup_times = ["2021-05-23T02:30:00Z"] } } - default_retention_rule { life_cycle { duration = "P12M" diff --git a/website/docs/r/data_protection_backup_policy_postgresql.html.markdown b/website/docs/r/data_protection_backup_policy_postgresql.html.markdown index 3407d655344e..90b6bb6c62d0 100644 --- a/website/docs/r/data_protection_backup_policy_postgresql.html.markdown +++ b/website/docs/r/data_protection_backup_policy_postgresql.html.markdown @@ -79,7 +79,11 @@ The following arguments are supported: * `backup_repeating_time_intervals` - (Required) Specifies a list of repeating time interval. It supports weekly back. It should follow `ISO 8601` repeating time interval. Changing this forces a new Backup Policy PostgreSQL to be created. -* `default_retention_duration` - (Required) The duration of default retention rule. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. +* `default_retention_duration` - (Optional) The duration of default retention rule. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. + +-> **Note:** `default_retention_duration` has been deprecated and will be removed in version 4.0 of the provider in favour of `default_retention_rule.0.life_cycle.#.duration`. + +* `default_retention_rule` - (Optional) A `default_retention_rule` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. * `retention_rule` - (Optional) One or more `retention_rule` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. @@ -87,16 +91,26 @@ The following arguments are supported: --- +A `default_retention_rule` block supports the following: + +* `life_cycle` - (Optional) One or more `life_cycle` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. + +--- + A `retention_rule` block supports the following: * `name` - (Required) The name which should be used for this retention rule. Changing this forces a new Backup Policy PostgreSQL to be created. -* `duration` - (Required) Duration after which the backup is deleted. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. - * `criteria` - (Required) A `criteria` block as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. * `priority` - (Required) Specifies the priority of the rule. The priority number must be unique for each rule. The lower the priority number, the higher the priority of the rule. Changing this forces a new Backup Policy PostgreSQL to be created. +* `duration` - (Optional) Duration after which the backup is deleted. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. + +-> **Note:** `duration` has been deprecated and will be removed in version 4.0 of the provider in favour of `life_cycle.#.duration`. + +* `life_cycle` - (Optional) One or more `life_cycle` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. + --- A `criteria` block supports the following: @@ -111,6 +125,24 @@ A `criteria` block supports the following: * `weeks_of_month` - (Optional) Possible values are `First`, `Second`, `Third`, `Fourth` and `Last`. Changing this forces a new Backup Policy PostgreSQL to be created. +--- + +A `life_cycle` block supports the following: + +* `data_store_type` - (Required) The type of data store. Possible values are `VaultStore`, `ArchiveStore`. Changing this forces a new Backup Policy PostgreSQL to be created. + +* `duration` - (Required) Duration after which the backup is deleted. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. + +* `target_copy_setting` - (Optional) A `target_copy_setting` block as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. + +--- + +A `target_copy_setting` block supports the following: + +* `copy_option` - (Required) Specifies when the backups are tiered across two or more selected data stores as a json encoded string. Changing this forces a new Backup Policy PostgreSQL to be created. + +* `data_store_type` - (Required) The type of data store. The only possible value is `ArchiveStore`. Changing this forces a new Backup Policy PostgreSQL to be created. + ## Attributes Reference In addition to the Arguments listed above - the following Attributes are exported: From 91c48fcfe15cbf876179e5ea7db456a0f0d606cc Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Thu, 7 Mar 2024 12:12:50 +0800 Subject: [PATCH 4/9] update code --- ..._backup_policy_postgresql_resource_test.go | 105 ++---------------- 1 file changed, 10 insertions(+), 95 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index cd3247712de4..e38dfb45a766 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" ) @@ -20,6 +21,9 @@ import ( type DataProtectionBackupPolicyPostgreSQLResource struct{} func TestAccDataProtectionBackupPolicyPostgreSQL_basicDeprecatedInV4(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ @@ -56,6 +60,9 @@ func TestAccDataProtectionBackupPolicyPostgreSQL_basic(t *testing.T) { } func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImportDeprecatedInV4(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ @@ -84,6 +91,9 @@ func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImport(t *testing.T) { } func TestAccDataProtectionBackupPolicyPostgreSQL_completeDeprecatedInV4(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ @@ -134,101 +144,6 @@ func TestAccDataProtectionBackupPolicyPostgreSQL_complete(t *testing.T) { }) } -func TestAccDataProtectionBackupPolicyPostgreSQL_updateDeprecatedInV4(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") - r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basicDeprecatedInV4(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep( - "default_retention_duration", - "default_retention_rule.#", - "default_retention_rule.0.%", - "default_retention_rule.0.life_cycle.#", - "default_retention_rule.0.life_cycle.0.%", - "default_retention_rule.0.life_cycle.0.data_store_type", - "default_retention_rule.0.life_cycle.0.duration", - ), - { - Config: r.completeDeprecatedInV4(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep( - "default_retention_duration", - "default_retention_rule.#", - "default_retention_rule.0.%", - "default_retention_rule.0.life_cycle.#", - "default_retention_rule.0.life_cycle.0.%", - "default_retention_rule.0.life_cycle.0.data_store_type", - "default_retention_rule.0.life_cycle.0.duration", - "retention_rule.0.duration", - "retention_rule.0.life_cycle.#", - "retention_rule.0.life_cycle.0.%", - "retention_rule.0.life_cycle.0.data_store_type", - "retention_rule.0.life_cycle.0.duration", - "retention_rule.1.duration", - "retention_rule.1.life_cycle.#", - "retention_rule.1.life_cycle.0.%", - "retention_rule.1.life_cycle.0.data_store_type", - "retention_rule.1.life_cycle.0.duration", - "retention_rule.2.duration", - "retention_rule.2.life_cycle.#", - "retention_rule.2.life_cycle.0.%", - "retention_rule.2.life_cycle.0.data_store_type", - "retention_rule.2.life_cycle.0.duration", - ), - { - Config: r.basicDeprecatedInV4(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep( - "default_retention_duration", - "default_retention_rule.#", - "default_retention_rule.0.%", - "default_retention_rule.0.life_cycle.#", - "default_retention_rule.0.life_cycle.0.%", - "default_retention_rule.0.life_cycle.0.data_store_type", - "default_retention_rule.0.life_cycle.0.duration", - ), - }) -} - -func TestAccDataProtectionBackupPolicyPostgreSQL_update(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") - r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - { - Config: r.complete(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) -} - func (r DataProtectionBackupPolicyPostgreSQLResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := backuppolicies.ParseBackupPolicyID(state.ID) if err != nil { From 05e0fac759b2c316186705ee5de5416859572459 Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Tue, 12 Mar 2024 11:32:53 +0800 Subject: [PATCH 5/9] fix comments --- ...ction_backup_policy_postgresql_resource.go | 28 +++++++++---------- ..._backup_policy_postgresql_resource_test.go | 8 +++--- ...ion_backup_policy_postgresql.html.markdown | 6 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go index b7b257ca6e60..fb7ec9a5fdc9 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go @@ -240,14 +240,14 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ValidateFunc: validate.ISO8601Duration, }, - "target_copy_setting": { + "target_copy": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "copy_option": { + "option_json": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -303,14 +303,14 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ValidateFunc: validate.ISO8601Duration, }, - "target_copy_setting": { + "target_copy": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "copy_option": { + "option_json": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -361,14 +361,14 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ValidateFunc: validate.ISO8601Duration, }, - "target_copy_setting": { + "target_copy": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "copy_option": { + "option_json": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -423,14 +423,14 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ValidateFunc: validate.ISO8601Duration, }, - "target_copy_setting": { + "target_copy": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "copy_option": { + "option_json": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -686,9 +686,9 @@ func expandBackupPolicyPostgreSQLLifeCycle(input []interface{}) []backuppolicies for _, item := range input { v := item.(map[string]interface{}) targetCopySettingList := make([]backuppolicies.TargetCopySetting, 0) - if tcs := v["target_copy_setting"].([]interface{}); len(tcs) > 0 { + if tcs := v["target_copy"].([]interface{}); len(tcs) > 0 { tcsv := tcs[0].(map[string]interface{}) - copyAfter, err := expandTargetCopySettingFromJSON(tcsv["copy_option"].(string)) + copyAfter, err := expandTargetCopySettingFromJSON(tcsv["option_json"].(string)) if err != nil { return results } @@ -1059,9 +1059,9 @@ func flattenBackupPolicyPostgreSQLBackupLifeCycleArray(input []backuppolicies.So dataStoreType = string(item.SourceDataStore.DataStoreType) results = append(results, map[string]interface{}{ - "duration": duration, - "target_copy_setting": targetDataStoreCopySetting, - "data_store_type": dataStoreType, + "duration": duration, + "target_copy": targetDataStoreCopySetting, + "data_store_type": dataStoreType, }) } return results @@ -1081,7 +1081,7 @@ func flattenBackupPolicyPostgreSQLBackupTargetDataStoreCopySettingArray(input *[ dataStoreType := string(item.DataStore.DataStoreType) results = append(results, map[string]interface{}{ - "copy_option": copyAfter, + "option_json": copyAfter, "data_store_type": dataStoreType, }) } diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index e38dfb45a766..82a3c46b35d8 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -321,8 +321,8 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { life_cycle { duration = "P12W" data_store_type = "VaultStore" - target_copy_setting { - copy_option = jsonencode({ + target_copy { + option_json = jsonencode({ objectType = "CopyOnExpiryOption" }) data_store_type = "ArchiveStore" @@ -342,8 +342,8 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { life_cycle { duration = "P12M" data_store_type = "VaultStore" - target_copy_setting { - copy_option = jsonencode({ + target_copy { + option_json = jsonencode({ objectType = "CopyOnExpiryOption" }) data_store_type = "ArchiveStore" diff --git a/website/docs/r/data_protection_backup_policy_postgresql.html.markdown b/website/docs/r/data_protection_backup_policy_postgresql.html.markdown index 90b6bb6c62d0..d910598efb04 100644 --- a/website/docs/r/data_protection_backup_policy_postgresql.html.markdown +++ b/website/docs/r/data_protection_backup_policy_postgresql.html.markdown @@ -133,13 +133,13 @@ A `life_cycle` block supports the following: * `duration` - (Required) Duration after which the backup is deleted. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. -* `target_copy_setting` - (Optional) A `target_copy_setting` block as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. +* `target_copy` - (Optional) A `target_copy` block as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. --- -A `target_copy_setting` block supports the following: +A `target_copy` block supports the following: -* `copy_option` - (Required) Specifies when the backups are tiered across two or more selected data stores as a json encoded string. Changing this forces a new Backup Policy PostgreSQL to be created. +* `option_json` - (Required) Specifies when the backups are tiered across two or more selected data stores as a json encoded string. Changing this forces a new Backup Policy PostgreSQL to be created. * `data_store_type` - (Required) The type of data store. The only possible value is `ArchiveStore`. Changing this forces a new Backup Policy PostgreSQL to be created. From 3e8582738f3fcb32c64a0fe20d13fec7878121e5 Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Wed, 23 Oct 2024 17:03:31 +0800 Subject: [PATCH 6/9] fix comments --- ...ction_backup_policy_postgresql_resource.go | 43 ++++++++++--------- ..._backup_policy_postgresql_resource_test.go | 34 +++++++-------- website/docs/5.0-upgrade-guide.html.markdown | 5 +++ 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go index fb7ec9a5fdc9..4d6fa0d596c3 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go @@ -176,7 +176,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, CustomizeDiff: pluginsdk.CustomizeDiffShim(func(ctx context.Context, diff *pluginsdk.ResourceDiff, v interface{}) error { - if !features.FourPointOhBeta() { + if !features.FivePointOhBeta() { retentionRules := diff.Get("retention_rule") defaultRetentionDuration := diff.Get("default_retention_duration") defaultRetentionRule := diff.Get("default_retention_rule") @@ -200,20 +200,22 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }), } - if !features.FourPointOhBeta() { + if !features.FivePointOhBeta() { resource.Schema["default_retention_duration"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ExactlyOneOf: []string{"default_retention_duration", "default_retention_rule"}, - Deprecated: "`default_retention_duration` should be removed in favour of the `default_retention_rule.0.life_cycle.#.duration` property in version 4.0 of the AzureRM Provider.", - ValidateFunc: validate.ISO8601Duration, + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ConflictsWith: []string{"default_retention_rule"}, + Deprecated: "`default_retention_duration` should be removed in favour of the `default_retention_rule.0.life_cycle.#.duration` property in version 5.0 of the AzureRM Provider.", + ValidateFunc: validate.ISO8601Duration, } resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["duration"] = &pluginsdk.Schema{ Type: pluginsdk.TypeString, Optional: true, ForceNew: true, - Deprecated: "`retention_rule.#.duration` should be removed in favour of the `retention_rule.#.life_cycle.#.duration` property in version 4.0 of the AzureRM Provider.", + Computed: true, + Deprecated: "`retention_rule.#.duration` should be removed in favour of the `retention_rule.#.life_cycle.#.duration` property in version 5.0 of the AzureRM Provider.", ValidateFunc: validate.ISO8601Duration, } resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"] = &pluginsdk.Schema{ @@ -259,7 +261,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. string(backuppolicies.DataStoreTypesArchiveStore), }, false), @@ -272,11 +274,12 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { } resource.Schema["default_retention_rule"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - ExactlyOneOf: []string{"default_retention_duration", "default_retention_rule"}, + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Computed: true, + MaxItems: 1, + ConflictsWith: []string{"default_retention_duration"}, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "life_cycle": { @@ -322,7 +325,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. string(backuppolicies.DataStoreTypesArchiveStore), }, false), @@ -380,7 +383,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. string(backuppolicies.DataStoreTypesArchiveStore), }, false), @@ -442,7 +445,7 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 4.0. + // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. string(backuppolicies.DataStoreTypesArchiveStore), }, false), @@ -491,7 +494,7 @@ func resourceDataProtectionBackupPolicyPostgreSQLCreate(d *pluginsdk.ResourceDat policyRules := make([]backuppolicies.BasePolicyRule, 0) policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureBackupRuleArray(d.Get("backup_repeating_time_intervals").([]interface{}), d.Get("time_zone").(string), taggingCriteria)...) - if v, ok := d.GetOk("default_retention_duration"); ok && !features.FourPointOhBeta() { + if v, ok := d.GetOk("default_retention_duration"); ok && !features.FivePointOhBeta() { policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultAzureRetentionRule(v)) policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRuleArray(d.Get("retention_rule").([]interface{}))...) } else { @@ -544,7 +547,7 @@ func resourceDataProtectionBackupPolicyPostgreSQLRead(d *pluginsdk.ResourceData, return fmt.Errorf("setting `backup_rule`: %+v", err) } - if _, ok := d.GetOk("default_retention_duration"); ok && !features.FourPointOhBeta() { + if _, ok := d.GetOk("default_retention_duration"); ok && !features.FivePointOhBeta() { if err := d.Set("default_retention_duration", flattenBackupPolicyPostgreSQLDefaultRetentionRuleDuration(&props.PolicyRules)); err != nil { return fmt.Errorf("setting `default_retention_duration`: %+v", err) } diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index 82a3c46b35d8..1044e6f25b8e 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -20,15 +20,15 @@ import ( type DataProtectionBackupPolicyPostgreSQLResource struct{} -func TestAccDataProtectionBackupPolicyPostgreSQL_basicDeprecatedInV4(t *testing.T) { - if features.FourPointOhBeta() { - t.Skip("this test requires 3.0 mode") +func TestAccDataProtectionBackupPolicyPostgreSQL_basicDeprecatedInV5(t *testing.T) { + if features.FivePointOhBeta() { + t.Skip("this test requires 4.0 mode") } data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.basicDeprecatedInV4(data), + Config: r.basicDeprecatedInV5(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), @@ -59,20 +59,20 @@ func TestAccDataProtectionBackupPolicyPostgreSQL_basic(t *testing.T) { }) } -func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImportDeprecatedInV4(t *testing.T) { - if features.FourPointOhBeta() { - t.Skip("this test requires 3.0 mode") +func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImportDeprecatedInV5(t *testing.T) { + if features.FivePointOhBeta() { + t.Skip("this test requires 4.0 mode") } data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.basicDeprecatedInV4(data), + Config: r.basicDeprecatedInV5(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), }, - data.RequiresImportErrorStep(r.requiresImportDeprecatedInV4), + data.RequiresImportErrorStep(r.requiresImportDeprecatedInV5), }) } @@ -90,15 +90,15 @@ func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImport(t *testing.T) { }) } -func TestAccDataProtectionBackupPolicyPostgreSQL_completeDeprecatedInV4(t *testing.T) { - if features.FourPointOhBeta() { - t.Skip("this test requires 3.0 mode") +func TestAccDataProtectionBackupPolicyPostgreSQL_completeDeprecatedInV5(t *testing.T) { + if features.FivePointOhBeta() { + t.Skip("this test requires 4.0 mode") } data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.completeDeprecatedInV4(data), + Config: r.completeDeprecatedInV5(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), @@ -180,7 +180,7 @@ resource "azurerm_data_protection_backup_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) basicDeprecatedInV4(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) basicDeprecatedInV5(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` %s @@ -218,8 +218,8 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { `, template, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImportDeprecatedInV4(data acceptance.TestData) string { - config := r.basicDeprecatedInV4(data) +func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImportDeprecatedInV5(data acceptance.TestData) string { + config := r.basicDeprecatedInV5(data) return fmt.Sprintf(` %s @@ -256,7 +256,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "import" { `, config) } -func (r DataProtectionBackupPolicyPostgreSQLResource) completeDeprecatedInV4(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) completeDeprecatedInV5(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` %s diff --git a/website/docs/5.0-upgrade-guide.html.markdown b/website/docs/5.0-upgrade-guide.html.markdown index 808a662ed3bb..735fc6af034c 100644 --- a/website/docs/5.0-upgrade-guide.html.markdown +++ b/website/docs/5.0-upgrade-guide.html.markdown @@ -55,6 +55,11 @@ Please follow the format in the example below for listing breaking changes in re * The deprecated `example_old_property` property has been removed in favour of the `example_new_property` property. * The deprecated `example_property_with_no_replacement` property has been removed. * The `example_property_with_changed_default` property now defaults to `NewDefault`. + +### `azurerm_data_protection_backup_policy_postgresql` + +* The deprecated `default_retention_duration` property has been removed in favour of the `default_retention_rule.0.life_cycle.#.duration` property. +* The deprecated `retention_rule.#.duration` property has been removed in favour of the `retention_rule.#.life_cycle.#.duration` property. ``` ### `azurerm_storage_account` From a030c6fdfc3050193e1ed6f25a3a745c02bd6e4a Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Wed, 23 Oct 2024 17:28:17 +0800 Subject: [PATCH 7/9] update doc --- .../r/data_protection_backup_policy_postgresql.html.markdown | 4 ---- 1 file changed, 4 deletions(-) diff --git a/website/docs/r/data_protection_backup_policy_postgresql.html.markdown b/website/docs/r/data_protection_backup_policy_postgresql.html.markdown index d910598efb04..483f6eb8ed42 100644 --- a/website/docs/r/data_protection_backup_policy_postgresql.html.markdown +++ b/website/docs/r/data_protection_backup_policy_postgresql.html.markdown @@ -81,8 +81,6 @@ The following arguments are supported: * `default_retention_duration` - (Optional) The duration of default retention rule. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. --> **Note:** `default_retention_duration` has been deprecated and will be removed in version 4.0 of the provider in favour of `default_retention_rule.0.life_cycle.#.duration`. - * `default_retention_rule` - (Optional) A `default_retention_rule` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. * `retention_rule` - (Optional) One or more `retention_rule` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. @@ -107,8 +105,6 @@ A `retention_rule` block supports the following: * `duration` - (Optional) Duration after which the backup is deleted. It should follow `ISO 8601` duration format. Changing this forces a new Backup Policy PostgreSQL to be created. --> **Note:** `duration` has been deprecated and will be removed in version 4.0 of the provider in favour of `life_cycle.#.duration`. - * `life_cycle` - (Optional) One or more `life_cycle` blocks as defined below. Changing this forces a new Backup Policy PostgreSQL to be created. --- From 29ddef5cf5be8add224620c88f8438b9e0827c94 Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Thu, 7 Nov 2024 13:44:34 +0800 Subject: [PATCH 8/9] fix comments --- ..._backup_policy_postgresql_resource_test.go | 169 +++++++----------- 1 file changed, 68 insertions(+), 101 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go index 1044e6f25b8e..b014139d2756 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource_test.go @@ -20,59 +20,37 @@ import ( type DataProtectionBackupPolicyPostgreSQLResource struct{} -func TestAccDataProtectionBackupPolicyPostgreSQL_basicDeprecatedInV5(t *testing.T) { - if features.FivePointOhBeta() { - t.Skip("this test requires 4.0 mode") - } - data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") - r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basicDeprecatedInV5(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep( - "default_retention_duration", - "default_retention_rule.#", - "default_retention_rule.0.%", - "default_retention_rule.0.life_cycle.#", - "default_retention_rule.0.life_cycle.0.%", - "default_retention_rule.0.life_cycle.0.data_store_type", - "default_retention_rule.0.life_cycle.0.duration", - ), - }) -} - func TestAccDataProtectionBackupPolicyPostgreSQL_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.basic(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), + if !features.FivePointOhBeta() { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", ), - }, - data.ImportStep(), - }) -} - -func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImportDeprecatedInV5(t *testing.T) { - if features.FivePointOhBeta() { - t.Skip("this test requires 4.0 mode") + }) + return } - data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") - r := DataProtectionBackupPolicyPostgreSQLResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.basicDeprecatedInV5(data), + Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), }, - data.RequiresImportErrorStep(r.requiresImportDeprecatedInV5), + data.ImportStep(), }) } @@ -90,49 +68,44 @@ func TestAccDataProtectionBackupPolicyPostgreSQL_requiresImport(t *testing.T) { }) } -func TestAccDataProtectionBackupPolicyPostgreSQL_completeDeprecatedInV5(t *testing.T) { - if features.FivePointOhBeta() { - t.Skip("this test requires 4.0 mode") - } - data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") - r := DataProtectionBackupPolicyPostgreSQLResource{} - data.ResourceTest(t, r, []acceptance.TestStep{ - { - Config: r.completeDeprecatedInV5(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep( - "default_retention_duration", - "default_retention_rule.#", - "default_retention_rule.0.%", - "default_retention_rule.0.life_cycle.#", - "default_retention_rule.0.life_cycle.0.%", - "default_retention_rule.0.life_cycle.0.data_store_type", - "default_retention_rule.0.life_cycle.0.duration", - "retention_rule.0.duration", - "retention_rule.0.life_cycle.#", - "retention_rule.0.life_cycle.0.%", - "retention_rule.0.life_cycle.0.data_store_type", - "retention_rule.0.life_cycle.0.duration", - "retention_rule.1.duration", - "retention_rule.1.life_cycle.#", - "retention_rule.1.life_cycle.0.%", - "retention_rule.1.life_cycle.0.data_store_type", - "retention_rule.1.life_cycle.0.duration", - "retention_rule.2.duration", - "retention_rule.2.life_cycle.#", - "retention_rule.2.life_cycle.0.%", - "retention_rule.2.life_cycle.0.data_store_type", - "retention_rule.2.life_cycle.0.duration", - ), - }) -} - func TestAccDataProtectionBackupPolicyPostgreSQL_complete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") r := DataProtectionBackupPolicyPostgreSQLResource{} + if !features.FivePointOhBeta() { + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "default_retention_duration", + "default_retention_rule.#", + "default_retention_rule.0.%", + "default_retention_rule.0.life_cycle.#", + "default_retention_rule.0.life_cycle.0.%", + "default_retention_rule.0.life_cycle.0.data_store_type", + "default_retention_rule.0.life_cycle.0.duration", + "retention_rule.0.duration", + "retention_rule.0.life_cycle.#", + "retention_rule.0.life_cycle.0.%", + "retention_rule.0.life_cycle.0.data_store_type", + "retention_rule.0.life_cycle.0.duration", + "retention_rule.1.duration", + "retention_rule.1.life_cycle.#", + "retention_rule.1.life_cycle.0.%", + "retention_rule.1.life_cycle.0.data_store_type", + "retention_rule.1.life_cycle.0.duration", + "retention_rule.2.duration", + "retention_rule.2.life_cycle.#", + "retention_rule.2.life_cycle.0.%", + "retention_rule.2.life_cycle.0.data_store_type", + "retention_rule.2.life_cycle.0.duration", + ), + }) + return + } data.ResourceTest(t, r, []acceptance.TestStep{ { Config: r.complete(data), @@ -180,9 +153,10 @@ resource "azurerm_data_protection_backup_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) basicDeprecatedInV5(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) basic(data acceptance.TestData) string { template := r.template(data) - return fmt.Sprintf(` + if !features.FivePointOhBeta() { + return fmt.Sprintf(` %s resource "azurerm_data_protection_backup_policy_postgresql" "test" { @@ -194,10 +168,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { default_retention_duration = "P4M" } `, template, data.RandomInteger) -} - -func (r DataProtectionBackupPolicyPostgreSQLResource) basic(data acceptance.TestData) string { - template := r.template(data) + } return fmt.Sprintf(` %s @@ -218,9 +189,10 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { `, template, data.RandomInteger) } -func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImportDeprecatedInV5(data acceptance.TestData) string { - config := r.basicDeprecatedInV5(data) - return fmt.Sprintf(` +func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImport(data acceptance.TestData) string { + config := r.basic(data) + if !features.FivePointOhBeta() { + return fmt.Sprintf(` %s resource "azurerm_data_protection_backup_policy_postgresql" "import" { @@ -232,10 +204,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "import" { default_retention_duration = "P4M" } `, config) -} - -func (r DataProtectionBackupPolicyPostgreSQLResource) requiresImport(data acceptance.TestData) string { - config := r.basic(data) + } return fmt.Sprintf(` %s @@ -256,9 +225,10 @@ resource "azurerm_data_protection_backup_policy_postgresql" "import" { `, config) } -func (r DataProtectionBackupPolicyPostgreSQLResource) completeDeprecatedInV5(data acceptance.TestData) string { +func (r DataProtectionBackupPolicyPostgreSQLResource) complete(data acceptance.TestData) string { template := r.template(data) - return fmt.Sprintf(` + if !features.FivePointOhBeta() { + return fmt.Sprintf(` %s resource "azurerm_data_protection_backup_policy_postgresql" "test" { @@ -302,10 +272,7 @@ resource "azurerm_data_protection_backup_policy_postgresql" "test" { } } `, template, data.RandomInteger) -} - -func (r DataProtectionBackupPolicyPostgreSQLResource) complete(data acceptance.TestData) string { - template := r.template(data) + } return fmt.Sprintf(` %s From 4716c04cfbc6d5ecb52a33e6fab472dd02b646b7 Mon Sep 17 00:00:00 2001 From: "Elena Xin (Centific Technologies Inc)" Date: Fri, 8 Nov 2024 14:14:22 +0800 Subject: [PATCH 9/9] fix comments --- ...ction_backup_policy_postgresql_resource.go | 368 ++++++------------ 1 file changed, 129 insertions(+), 239 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go index 4d6fa0d596c3..4ffaaafb39ef 100644 --- a/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go +++ b/internal/services/dataprotection/data_protection_backup_policy_postgresql_resource.go @@ -73,6 +73,71 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, }, + "default_retention_rule": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "life_cycle": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // confirmed with the service team that the possible values do not include `OperationalStore`. + string(backuppolicies.DataStoreTypesVaultStore), + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + + "duration": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + }, + + "target_copy": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "option_json": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsJSON, + }, + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // since the following feedback from the service team, the current possible values only support `ArchiveStore`. + // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. + // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "retention_rule": { Type: pluginsdk.TypeList, Optional: true, @@ -158,6 +223,61 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { }, }, + "life_cycle": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // confirmed with the service team that the possible values do not include `OperationalStore`. + string(backuppolicies.DataStoreTypesVaultStore), + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + + "duration": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ISO8601Duration, + }, + + "target_copy": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "option_json": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsJSON, + }, + "data_store_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + // since the following feedback from the service team, the current possible values only support `ArchiveStore`. + // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. + // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. + string(backuppolicies.DataStoreTypesArchiveStore), + }, false), + }, + }, + }, + }, + }, + }, + }, + "priority": { Type: pluginsdk.TypeInt, Required: true, @@ -210,6 +330,8 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { Deprecated: "`default_retention_duration` should be removed in favour of the `default_retention_rule.0.life_cycle.#.duration` property in version 5.0 of the AzureRM Provider.", ValidateFunc: validate.ISO8601Duration, } + + // Since the length of `retention_rule` may be greater than 1, it cannot be set via `ConflictsWith`, the conflict check is performed in CustomizeDiff. resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["duration"] = &pluginsdk.Schema{ Type: pluginsdk.TypeString, Optional: true, @@ -218,247 +340,15 @@ func resourceDataProtectionBackupPolicyPostgreSQL() *pluginsdk.Resource { Deprecated: "`retention_rule.#.duration` should be removed in favour of the `retention_rule.#.life_cycle.#.duration` property in version 5.0 of the AzureRM Provider.", ValidateFunc: validate.ISO8601Duration, } - resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // confirmed with the service team that the possible values do not include `OperationalStore`. - string(backuppolicies.DataStoreTypesVaultStore), - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - "duration": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ISO8601Duration, - }, + resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"].Required = false + resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"].Optional = true + resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"].Computed = true - "target_copy": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "option_json": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsJSON, - }, - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. - // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - }, - }, - }, - }, - }, - } - - resource.Schema["default_retention_rule"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - Computed: true, - MaxItems: 1, - ConflictsWith: []string{"default_retention_duration"}, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "life_cycle": { - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // confirmed with the service team that the possible values do not include `OperationalStore`. - string(backuppolicies.DataStoreTypesVaultStore), - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - - "duration": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ISO8601Duration, - }, - - "target_copy": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "option_json": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsJSON, - }, - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. - // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - } else { - resource.Schema["retention_rule"].Elem.(*pluginsdk.Resource).Schema["life_cycle"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // confirmed with the service team that the possible values do not include `OperationalStore`. - string(backuppolicies.DataStoreTypesVaultStore), - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - - "duration": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ISO8601Duration, - }, - - "target_copy": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "option_json": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsJSON, - }, - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // However, in view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. - // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - }, - }, - }, - }, - }, - } - - resource.Schema["default_retention_rule"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "life_cycle": { - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // confirmed with the service team that the possible values do not include `OperationalStore`. - string(backuppolicies.DataStoreTypesVaultStore), - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - - "duration": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ISO8601Duration, - }, - - "target_copy": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "option_json": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsJSON, - }, - "data_store_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - // since the following feedback from the service team, the current possible values only support `ArchiveStore`. - // In view of possible support for `VaultStore` in the future, the `data_store_type` property is exposed for users to set in version 5.0. - // feedback from the service team: Theoretically all 3 values possible. But currently only logical combination is from VaultStore to ArchiveStore. So in target data store it can only be ArchiveStore. OperationalStore isn’t supported for this workload. - string(backuppolicies.DataStoreTypesArchiveStore), - }, false), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } + resource.Schema["default_retention_rule"].Required = false + resource.Schema["default_retention_rule"].Optional = true + resource.Schema["default_retention_rule"].Computed = true + resource.Schema["default_retention_rule"].ConflictsWith = []string{"default_retention_duration"} } return resource