azurerm_data_protection_backup_policy_postgresql: support target_copy property and its related updates#24476
azurerm_data_protection_backup_policy_postgresql: support target_copy property and its related updates#24476sinbai wants to merge 11 commits intohashicorp:mainfrom
azurerm_data_protection_backup_policy_postgresql: support target_copy property and its related updates#24476Conversation
katbyte
left a comment
There was a problem hiding this comment.
Thanks @sinbai - this looks like the new property won't take affect till 4.0?
is it possible to implement them now inline and support a graceful deprecation path for users instead of the hard breaking change in 4.0? as well allowing them to be used before?
Hi @katbyte thanks for your feedback and sounds like good suggestion. However, the newly added properties |
|
Changing something from optional -> required during a major version is just fine! so lets make it optional & enable people using these properties now with the 4.0 flag flipping it to how things should behave in 4.0 |
8d946c6 to
ed5ce33
Compare
Hi @katbyte thanks for your time and feedback. I have updated the code. Could you please take another look? Test results are as follows: |
|
|
||
| --- | ||
|
|
||
| A `target_copy_setting` block supports the following: |
There was a problem hiding this comment.
I think setting is redundant?
| A `target_copy_setting` block supports the following: | |
| A `target_copy` block supports the following: |
|
|
||
| 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. |
There was a problem hiding this comment.
and this might be better as
| * `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. |
?
| "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", |
There was a problem hiding this comment.
are these not returned from the API? how come we are ignoring them?
There was a problem hiding this comment.
The API returns their values. However, TF supports both default_retention_duration (deprecated in v4.0) and default_retention_rule, which are two mutually exclusive properties in v3.0. These two properties corresponding to the same property of the API. Therefore, when importing resource in v3.0, I assume that we have no way of knowing whether the default_retention_duration or default_retention_rule is specified in the config, so I ignore them. Please see the following code in resourceDataProtectionBackupPolicyPostgreSQLRead func for details. Other than that, could you please let me know if there is a better solution?

There was a problem hiding this comment.
in the past when i have deprecated a property and replaced it with another property i've made them both computed and then just set them both in read so they have a valid property, and then only sent the value that exists/has been set in config off to the api in update/create.
is this possible with these fields to do that?
There was a problem hiding this comment.
Hi @katbyte thank you very much, I think this is a very good way. But there is a little problem. If the deprecated and replaced properties are set in read at the same time, then the following checks need to be deleted at the same time. Do you think it's okay to remove the check?

There was a problem hiding this comment.
Hi @katbyte a kind reminder in case you miss the above message.
|
Hi @katbyte I have updated the code to fix the comments above. The test results are as follows, could you please take another look? Thanks for your time. |
|
This PR is being labeled as "stale" because it has not been updated for 30 or more days. If this PR is still valid, please remove the "stale" label. If this PR is blocked, please add it to the "Blocked" milestone. If you need some help completing this PR, please leave a comment letting us know. Thank you! |
|
This PR is being labeled as "stale" because it has not been updated for 30 or more days. If this PR is still valid, please remove the "stale" label. If this PR is blocked, please add it to the "Blocked" milestone. If you need some help completing this PR, please leave a comment letting us know. Thank you! |
|
@sinbai having taken another look, this will require some significant rework before this can go in. Before we go down that path though I have a specific question which is: Has the request to add support for I ask because when creating a Backup Policy for PostgreSQL in the Portal, the option target copy setting isn't exposed at all and there is no way to set that information in the policy currently. See the JSON excerpt below of the Backup Policy created via the portal: |
Hi @stephybun sorry for the late reply. Yes, support for |
|
@sinbai as per discussed on tuesday here is the breaking change & deprecation guide that this PR should follow: https://github.com/hashicorp/terraform-provider-azurerm/commits/main/contributing/topics/guide-breaking-changes.md |
Hi @katbyte , thanks for your time. I'm assuming I've followed the breaking changes and deprecation guidelines for now, please let me know if I've missed/misunderstood something. Thank you! |
jackofallops
left a comment
There was a problem hiding this comment.
Hi @sinbai - Sorry for the delay on this.
Can you update the title of this PR to reflect the change, it doesn't appear to have anything to do with target_copy_setting, rather you're adding an entire block and deprecating a string property, to add support for target_copy.
Additionally, there are some important points to take a look at below if you could. Once these are addressed, I'll loop back to continue review.
Thanks
| CustomizeDiff: pluginsdk.CustomizeDiffShim(func(ctx context.Context, diff *pluginsdk.ResourceDiff, v interface{}) error { | ||
| if !features.FivePointOhBeta() { | ||
| 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 | ||
| }), |
There was a problem hiding this comment.
Can we move this into the feature flagged block below, it will make it easier and safer to remove after the 5.0 release.
| 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.", |
There was a problem hiding this comment.
Grammar, and formatting as per the deprecation guide.
| 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.", | |
| Deprecated: "`default_retention_duration` has been deprecated in favour of the `default_retention_rule.0.life_cycle.#.duration` and will be removed in version 5.0 of the AzureRM Provider.", |
| Optional: true, | ||
| ForceNew: true, | ||
| 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.", |
There was a problem hiding this comment.
Grammar, and formatting as per the deprecation guide.
| 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.", | |
| Deprecated: "`retention_rule.#.duration` has been deprecated in favour of the `retention_rule.#.life_cycle.#.duration` and will be removed in version 5.0 of the AzureRM Provider.", |
| }), | ||
| } | ||
|
|
||
| if !features.FivePointOhBeta() { |
There was a problem hiding this comment.
This function has been removed, can you any instances update to use features.FivePointOh() please.
| 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 { | ||
| policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultRetentionRule(d.Get("default_retention_rule").([]interface{}))) | ||
| policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRules(d.Get("retention_rule").([]interface{}))...) | ||
| } |
There was a problem hiding this comment.
I think this can be changed to make it easier to remove when 5.0 ships:
| 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 { | |
| policyRules = append(policyRules, expandBackupPolicyPostgreSQLDefaultRetentionRule(d.Get("default_retention_rule").([]interface{}))) | |
| policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRules(d.Get("retention_rule").([]interface{}))...) | |
| } | |
| if !features.FivePointOh() { | |
| if v, ok := d.GetOk("default_retention_duration"); ok { | |
| 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{}))) | |
| policyRules = append(policyRules, expandBackupPolicyPostgreSQLAzureRetentionRules(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{}))...) | |
| } | |
| 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) | ||
| } | ||
| 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) | ||
| } | ||
| } |
There was a problem hiding this comment.
This will break importing the resource in almost all cases (which is why you had to ignore more or less everything in the test below). This will need to be reworked to allow those tests to pass correctly without ignoring the import errors.
| func TestAccDataProtectionBackupPolicyPostgreSQL_basic(t *testing.T) { | ||
| data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_policy_postgresql", "test") | ||
| r := DataProtectionBackupPolicyPostgreSQLResource{} | ||
| if !features.FivePointOhBeta() { |
There was a problem hiding this comment.
These tests need to be split into 4.x and 5.0 versions, since they have differing functionality, and currently they will require significant effort to resolve/make right when 5.0 ships.
azurerm_data_protection_backup_policy_postgresql: support target_copy_setting propertyazurerm_data_protection_backup_policy_postgresql: support target_copy property and its related updates
Hi @jackofallops thanks for your feedback. I have updated the code, could you please take another look? |
|
Close this as |




When supporting targetDataStoreCopySettings property, it was found that TF is currently hard-coded for default azure retention rule and source data store partial value for the lifecycles(Additionally, there is the fact that for the default Azure retention rules/Azure retention rule, the lifecycle may have multiple items instead of the current hard-coded single item). The service team has confirmed that these properties are not immutable. I assume that these properties should be specified by the user.
Therefore, while submitting this PR to support
targetDataStoreCopySettings, the original implementation (dependency) was changed and some properties were opened to users.Test results:
