Skip to content

Commit

Permalink
backup_plan - fix idempotency issue with botocore >= 1.31.36 (#1961) (#…
Browse files Browse the repository at this point in the history
…1962)

[PR #1961/c8064d5c backport][stable-7] backup_plan - fix idempotency issue with botocore >= 1.31.36

This is a backport of PR #1961 as merged into main (c8064d5).
SUMMARY

Fixes #1952
backup_plan - fix idempotency issue with botocore >= 1.31.36

ISSUE TYPE


Bugfix Pull Request
Feature Pull Request

Reviewed-by: Alina Buzachis
  • Loading branch information
patchback[bot] authored Feb 5, 2024
1 parent 6afbd73 commit ddb39e0
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 0 deletions.
6 changes: 6 additions & 0 deletions changelogs/fragments/20240202-backup_plan-idempotency.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bugfixes:
- backup_plan - Fix idempotency issue when using botocore >= 1.31.36 (https://github.com/ansible-collections/amazon.aws/issues/1952).

minor_changes:
- backup_plan - Let user to set ``schedule_expression_timezone`` for
backup plan rules when when using botocore >= 1.31.36 (https://github.com/ansible-collections/amazon.aws/issues/1952).
84 changes: 84 additions & 0 deletions plugins/modules/backup_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@
- AWS default if not supplied is false.
type: bool
default: false
schedule_expression_timezone:
description:
- This is the timezone in which the schedule expression is set.
- By default, ScheduleExpressions are in UTC. You can modify this to a specified timezone.
- This option requires botocore >= 1.31.36.
type: str
default: "Etc/UTC"
required: false
version_added: 7.3.0
advanced_backup_settings:
description:
- Specifies a list of advanced backup settings for each resource type.
Expand Down Expand Up @@ -233,6 +242,70 @@
returned: always
type: list
elements: dict
contains:
rule_name:
description: A display name for a backup rule.
returned: always
type: str
sample: "daily"
target_backup_vault_name:
description: The name of a logical container where backups are stored.
returned: always
type: str
sample: 09da67966fd5-backup-vault"
schedule_expression:
description: A cron expression in UTC specifying when Backup initiates a backup job.
returned: always
type: str
sample: "cron(0 5 ? * * *)"
start_window_minutes:
description:
- A value in minutes after a backup is scheduled before a job will be canceled if it
doesn't start successfully.
type: int
sample: 480
completion_window_minutes:
description:
- A value in minutes after a backup job is successfully started before it must be
completed or it will be canceled by Backup.
type: int
sample: 10080
lifecycle:
description:
- The lifecycle defines when a protected resource is transitioned to cold storage and when
it expires.
type: dict
sample: {}
recovery_point_tags:
description:
- An array of key-value pair strings that are assigned to resources that are associated with
this rule when restored from backup.
type: dict
sample: {}
rule_id:
description:
- Uniquely identifies a rule that is used to schedule the backup of a selection of resources.
type: str
returned: always
sample: "973621ef-d863-41ef-b5c3-9e943a64ad0c"
copy_actions:
description: An array of CopyAction objects, which contains the details of the copy operation.
type: list
returned: always
sample: []
enable_continous_backup:
description: Specifies whether Backup creates continuous backups.
type: bool
returned: always
sample: false
schedule_expression_timezone:
description:
- This is the timezone in which the schedule expression is set.
- This information is returned for botocore versions >= 1.31.36.
type: str
returned: when botocore >= 1.31.36
sample: "Etc/UTC"
version_added: 7.3.0
advanced_backup_settings:
description: Advanced backup settings of the backup plan.
returned: when configured
Expand Down Expand Up @@ -281,6 +354,7 @@
schedule_expression=dict(type="str", default="cron(0 5 ? * * *)"),
start_window_minutes=dict(type="int", default=480),
completion_window_minutes=dict(type="int", default=10080),
schedule_expression_timezone=dict(type="str", default="Etc/UTC"),
lifecycle=dict(
type="dict",
options=dict(
Expand Down Expand Up @@ -542,13 +616,23 @@ def main():
client = module.client("backup")
state = module.params["state"]
plan_name = module.params["backup_plan_name"]

plan = {
"backup_plan_name": module.params["backup_plan_name"],
"rules": [scrub_none_parameters(rule) for rule in module.params["rules"] or []],
"advanced_backup_settings": [
scrub_none_parameters(setting) for setting in module.params["advanced_backup_settings"] or []
],
}

if module.params["rules"]:
for each in plan["rules"]:
if not module.botocore_at_least("1.31.36"):
module.warn(
"schedule_expression_timezone requires botocore >= 1.31.36. schedule_expression_timezone will be ignored."
)
each.pop("schedule_expression_timezone")

tags = module.params["tags"]

# Get existing backup plan details and ID if present
Expand Down
5 changes: 5 additions & 0 deletions tests/integration/targets/backup_plan/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
dependencies:
- role: setup_botocore_pip
vars:
botocore_version: "1.31.36"
39 changes: 39 additions & 0 deletions tests/integration/targets/backup_plan/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,45 @@
- backup_plan_delete_result.backup_plan_arn == backup_plan_info.backup_plans[0].backup_plan_arn
- backup_plan_delete_result.deletion_date is defined

- name: Create a backup plan using specific botocore version
amazon.aws.backup_plan:
backup_plan_name: "{{ backup_plan_name }}"
rules:
- rule_name: daily
target_backup_vault_name: "{{ backup_vault_name }}"
tags:
Environment: Test
register: backup_plan_create_result
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- name: Verify backup plan create result
ansible.builtin.assert:
that:
- backup_plan_create_result.exists is true
- backup_plan_create_result.changed is true
- backup_plan_create_result.backup_plan_name == backup_plan_name
- backup_plan_create_result.backup_plan.rules != []
- "backup_plan_create_result.backup_plan.rules | selectattr('schedule_expression_timezone', 'match', 'Etc/UTC') | list"

- name: Create a backup plan using specific botocore version (idempotency)
amazon.aws.backup_plan:
backup_plan_name: "{{ backup_plan_name }}"
rules:
- rule_name: daily
target_backup_vault_name: "{{ backup_vault_name }}"
tags:
Environment: Test
register: backup_plan_create_result
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- name: Verify backup plan create result
ansible.builtin.assert:
that:
- backup_plan_create_result.exists is true
- backup_plan_create_result.changed is false

always:
- name: Delete AWS Backup plan created during this test
amazon.aws.backup_plan:
Expand Down

0 comments on commit ddb39e0

Please sign in to comment.