Skip to content

Commit

Permalink
make s3_lifecycle not call put_lifecycle_configuration if there is no…
Browse files Browse the repository at this point in the history
… change to put (#1629) (#1647)

[PR #1629/5aa3ff17 backport][stable-4] make s3_lifecycle not call put_lifecycle_configuration if there is no…

This is a backport of PR #1629 as merged into main (5aa3ff1).
SUMMARY
Fixes #1624
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
s3_lifecycle
ADDITIONAL INFORMATION
I have not written integration tests for this. My MWE in #1624 used multiple hosts (all localhost). I don't know how to add that here.

Reviewed-by: Markus Bergholz <[email protected]>
  • Loading branch information
patchback[bot] authored Jan 12, 2023
1 parent 9643eb3 commit d0c5238
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 62 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/1624-s3-lifecycle-idempotent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- s3_lifecycle - Module no longer calls `put_lifecycle_configuration` if there is no change. (https://github.com/ansible-collections/community.aws/issues/1624)
129 changes: 67 additions & 62 deletions plugins/modules/s3_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,38 +466,40 @@ def create_lifecycle_rule(client, module):
(changed, lifecycle_configuration) = compare_and_update_configuration(client, module,
old_lifecycle_rules,
new_rule)

# Write lifecycle to bucket
try:
client.put_bucket_lifecycle_configuration(
aws_retry=True,
Bucket=name,
LifecycleConfiguration=lifecycle_configuration)
except is_boto3_error_message('At least one action needs to be specified in a rule'):
# Amazon interpretted this as not changing anything
changed = False
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except
module.fail_json_aws(e, lifecycle_configuration=lifecycle_configuration, name=name, old_lifecycle_rules=old_lifecycle_rules)

_changed = changed
_retries = 10
_not_changed_cnt = 6
while wait and _changed and _retries and _not_changed_cnt:
# We've seen examples where get_bucket_lifecycle_configuration returns
# the updated rules, then the old rules, then the updated rules again and
# again couple of times.
# Thus try to read the rule few times in a row to check if it has changed.
time.sleep(5)
_retries -= 1
new_rules = fetch_rules(client, module, name)
(_changed, lifecycle_configuration) = compare_and_update_configuration(client, module,
new_rules,
new_rule)
if not _changed:
_not_changed_cnt -= 1
_changed = True
else:
_not_changed_cnt = 6
if changed:
# Write lifecycle to bucket
try:
client.put_bucket_lifecycle_configuration(
aws_retry=True,
Bucket=name,
LifecycleConfiguration=lifecycle_configuration)
except is_boto3_error_message('At least one action needs to be specified in a rule'):
# Amazon interpretted this as not changing anything
changed = False
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except
module.fail_json_aws(e, lifecycle_configuration=lifecycle_configuration, name=name, old_lifecycle_rules=old_lifecycle_rules)

_changed = changed
_retries = 10
_not_changed_cnt = 6
while wait and _changed and _retries and _not_changed_cnt:
# We've seen examples where get_bucket_lifecycle_configuration returns
# the updated rules, then the old rules, then the updated rules again and
# again couple of times.
# Thus try to read the rule few times in a row to check if it has changed.
time.sleep(5)
_retries -= 1
new_rules = fetch_rules(client, module, name)
(_changed, lifecycle_configuration) = compare_and_update_configuration(client, module,
new_rules,
new_rule)
if not _changed:
_not_changed_cnt -= 1
_changed = True
else:
_not_changed_cnt = 6
else:
_retries = 0

new_rules = fetch_rules(client, module, name)

Expand All @@ -520,36 +522,39 @@ def destroy_lifecycle_rule(client, module):
current_lifecycle_rules = fetch_rules(client, module, name)
changed, lifecycle_obj = compare_and_remove_rule(current_lifecycle_rules, rule_id, prefix)

# Write lifecycle to bucket or, if there no rules left, delete lifecycle configuration
try:
if lifecycle_obj['Rules']:
client.put_bucket_lifecycle_configuration(
aws_retry=True,
Bucket=name,
LifecycleConfiguration=lifecycle_obj)
elif current_lifecycle_rules:
changed = True
client.delete_bucket_lifecycle(aws_retry=True, Bucket=name)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e)

_changed = changed
_retries = 10
_not_changed_cnt = 6
while wait and _changed and _retries and _not_changed_cnt:
# We've seen examples where get_bucket_lifecycle_configuration returns
# the updated rules, then the old rules, then the updated rules again and
# again couple of times.
# Thus try to read the rule few times in a row to check if it has changed.
time.sleep(5)
_retries -= 1
new_rules = fetch_rules(client, module, name)
(_changed, lifecycle_configuration) = compare_and_remove_rule(new_rules, rule_id, prefix)
if not _changed:
_not_changed_cnt -= 1
_changed = True
else:
_not_changed_cnt = 6
if changed:
# Write lifecycle to bucket or, if there no rules left, delete lifecycle configuration
try:
if lifecycle_obj['Rules']:
client.put_bucket_lifecycle_configuration(
aws_retry=True,
Bucket=name,
LifecycleConfiguration=lifecycle_obj)
elif current_lifecycle_rules:
changed = True
client.delete_bucket_lifecycle(aws_retry=True, Bucket=name)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e)

_changed = changed
_retries = 10
_not_changed_cnt = 6
while wait and _changed and _retries and _not_changed_cnt:
# We've seen examples where get_bucket_lifecycle_configuration returns
# the updated rules, then the old rules, then the updated rules again and
# again couple of times.
# Thus try to read the rule few times in a row to check if it has changed.
time.sleep(5)
_retries -= 1
new_rules = fetch_rules(client, module, name)
(_changed, lifecycle_configuration) = compare_and_remove_rule(new_rules, rule_id, prefix)
if not _changed:
_not_changed_cnt -= 1
_changed = True
else:
_not_changed_cnt = 6
else:
_retries = 0

new_rules = fetch_rules(client, module, name)

Expand Down

0 comments on commit d0c5238

Please sign in to comment.