Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[PR #1606/3391b27d backport][stable-5] s3_lifecycle - ability to set the number of newest noncurrent versions to retain #1687

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- s3_lifecycle - add parameter `noncurrent_version_keep_newer` to set the number of newest noncurrent versions to retain
51 changes: 38 additions & 13 deletions plugins/modules/s3_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,17 @@
noncurrent_version_expiration_days:
description:
- The number of days after which non-current versions should be deleted.
- Must be set if I(noncurrent_version_keep_newer) is set.
required: false
type: int
noncurrent_version_keep_newer:
description:
- The minimum number of non-current versions to retain.
- Requires C(botocore >= 1.23.12)
- Requres I(noncurrent_version_expiration_days).
required: false
type: int
version_added: 5.3.0
noncurrent_version_storage_class:
description:
- The storage class to which non-current versions are transitioned.
Expand Down Expand Up @@ -269,6 +278,7 @@ def build_rule(client, module):
noncurrent_version_transition_days = module.params.get("noncurrent_version_transition_days")
noncurrent_version_transitions = module.params.get("noncurrent_version_transitions")
noncurrent_version_storage_class = module.params.get("noncurrent_version_storage_class")
noncurrent_version_keep_newer = module.params.get("noncurrent_version_keep_newer")
prefix = module.params.get("prefix") or ""
rule_id = module.params.get("rule_id")
status = module.params.get("status")
Expand All @@ -294,10 +304,12 @@ def build_rule(client, module):
rule['Expiration'] = dict(Date=expiration_date.isoformat())
elif expire_object_delete_marker is not None:
rule['Expiration'] = dict(ExpiredObjectDeleteMarker=expire_object_delete_marker)

if noncurrent_version_expiration_days or noncurrent_version_keep_newer:
rule['NoncurrentVersionExpiration'] = dict()
if noncurrent_version_expiration_days is not None:
rule['NoncurrentVersionExpiration'] = dict(NoncurrentDays=noncurrent_version_expiration_days)

rule['NoncurrentVersionExpiration']['NoncurrentDays'] = noncurrent_version_expiration_days
if noncurrent_version_keep_newer is not None:
rule['NoncurrentVersionExpiration']['NewerNoncurrentVersions'] = noncurrent_version_keep_newer
if transition_days is not None:
rule['Transitions'] = [dict(Days=transition_days, StorageClass=storage_class.upper()), ]

Expand Down Expand Up @@ -572,6 +584,7 @@ def main():
expiration_date=dict(),
expire_object_delete_marker=dict(type='bool'),
noncurrent_version_expiration_days=dict(type='int'),
noncurrent_version_keep_newer=dict(type='int'),
noncurrent_version_storage_class=dict(default='glacier', type='str', choices=s3_storage_class),
noncurrent_version_transition_days=dict(type='int'),
noncurrent_version_transitions=dict(type='list', elements='dict'),
Expand All @@ -587,29 +600,41 @@ def main():
wait=dict(type='bool', default=False)
)

module = AnsibleAWSModule(argument_spec=argument_spec,
mutually_exclusive=[
['expiration_days', 'expiration_date', 'expire_object_delete_marker'],
['expiration_days', 'transition_date'],
['transition_days', 'transition_date'],
['transition_days', 'expiration_date'],
['transition_days', 'transitions'],
['transition_date', 'transitions'],
['noncurrent_version_transition_days', 'noncurrent_version_transitions'],
],)
module = AnsibleAWSModule(
argument_spec=argument_spec,
mutually_exclusive=[
["expiration_days", "expiration_date", "expire_object_delete_marker"],
["expiration_days", "transition_date"],
["transition_days", "transition_date"],
["transition_days", "expiration_date"],
["transition_days", "transitions"],
["transition_date", "transitions"],
["noncurrent_version_transition_days", "noncurrent_version_transitions"],
],
required_by={
"noncurrent_version_keep_newer": ["noncurrent_version_expiration_days"],
},
)

client = module.client('s3', retry_decorator=AWSRetry.jittered_backoff())

expiration_date = module.params.get("expiration_date")
transition_date = module.params.get("transition_date")
state = module.params.get("state")

if module.params.get("noncurrent_version_keep_newer"):
module.require_botocore_at_least(
"1.23.12",
reason="to set number of versions to keep with noncurrent_version_keep_newer"
)

if state == 'present' and module.params["status"] == "enabled": # allow deleting/disabling a rule by id/prefix

required_when_present = ('abort_incomplete_multipart_upload_days',
'expiration_date', 'expiration_days', 'expire_object_delete_marker',
'transition_date', 'transition_days', 'transitions',
'noncurrent_version_expiration_days',
'noncurrent_version_keep_newer',
'noncurrent_version_transition_days',
'noncurrent_version_transitions')
for param in required_when_present:
Expand Down
5 changes: 4 additions & 1 deletion tests/integration/targets/s3_lifecycle/meta/main.yml
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
dependencies: []
dependencies:
- role: setup_botocore_pip
vars:
botocore_version: "1.23.12"
53 changes: 52 additions & 1 deletion tests/integration/targets/s3_lifecycle/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,6 @@
that:
- output is changed

# ============================================================
- name: Create a lifecycle policy, with expired_object_delete_marker (idempotency)
s3_lifecycle:
name: '{{ bucket_name }}'
Expand All @@ -435,6 +434,58 @@
that:
- output is not changed

# ============================================================
- name: Update lifecycle policy, with noncurrent_version_expiration_days
s3_lifecycle:
name: '{{ bucket_name }}'
noncurrent_version_expiration_days: 5
prefix: /something
register: output

- assert:
that:
- output is changed

- name: Update lifecycle policy, with noncurrent_version_expiration_days (idempotency)
s3_lifecycle:
name: '{{ bucket_name }}'
noncurrent_version_expiration_days: 5
prefix: /something
register: output

- assert:
that:
- output is not changed

# ============================================================
- name: Update lifecycle policy, with noncurrent_version_keep_newer
s3_lifecycle:
name: '{{ bucket_name }}'
noncurrent_version_expiration_days: 10
noncurrent_version_keep_newer: 6
prefix: /something
register: output
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- assert:
that:
- output is changed

- name: Update lifecycle policy, with noncurrent_version_keep_newer (idempotency)
s3_lifecycle:
name: '{{ bucket_name }}'
noncurrent_version_expiration_days: 10
noncurrent_version_keep_newer: 6
prefix: /something
register: output
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- assert:
that:
- output is not changed

# ============================================================
# test all the examples
# Configure a lifecycle rule on a bucket to expire (delete) items with a prefix of /logs/ after 30 days
Expand Down