Fix s3_lifecycle to work with new and old syntax of lifecycle | fix idempotency | fix duplicate lifecycle rule per execution - #2374
Open
rfakit wants to merge 1 commit into
Conversation
…of s3 lifecycle policy
Contributor
|
Build succeeded. ✔️ ansible-galaxy-importer SUCCESS in 4m 58s (non-voting) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix: Prevent S3 Lifecycle Policy Duplication When rule_id is Specified
Problem Description
The
s3_lifecycleAnsible module was creating duplicate lifecycle rules on every playbook run when arule_idwas specified in the configuration. This occurred because the module only matched existing rules by their ID, and when existing rules had auto-generated IDs (which S3 creates when no ID is provided), they were not recognized as matches, causing new rules to be created on each execution.Symptoms
changed: trueon every run even when the desired state already exists{ "Rules": [ {"ID": "5voiavj06zkjjrhwud205tkaxriivj2om0k82qa1c3l52zwo", "Expiration": {"Days": 1}, "Prefix": "", "Status": "Enabled"}, {"ID": "ID-1", "Expiration": {"Days": 1}, "Prefix": "", "Status": "Enabled"}, {"ID": "us944tgwgbxl52sjwt6mudd0ibpzf7wx6q6zeug8dx5ekjdh", "Expiration": {"Days": 1}, "Prefix": "", "Status": "Enabled"}, {"ID": "w09je6ajineekl5yy5adz9b7d1sw68nq1g5rtaw3n2k8qla8", "Expiration": {"Days": 1}, "Prefix": "", "Status": "Enabled"} ] }Root Cause Analysis
ID-Only Matching: The module's
compare_and_update_configuration()function only attempted to match existing rules by their ID. When arule_idwas provided (e.g., "ID-1"), it would look for an existing rule with that exact ID. If no match was found (because existing rules had auto-generated IDs), it would create a new rule.Format Incompatibility: S3 lifecycle rules can exist in two formats:
{"Prefix": "", "Status": "Enabled", ...}(Prefix directly on the rule){"Filter": {"Prefix": ""}, "Status": "Enabled", ...}(Filter object)The module's comparison logic didn't handle both formats consistently, causing mismatches even when rules were functionally identical.
No Duplicate Cleanup: When duplicate rules were created, the module didn't remove existing duplicates, only added new ones.
Solution
The fix implements a multi-layered approach:
Rule Format Normalization: Added
normalize_rule_format()to convert all rules to a consistent format (new Filter format) when fetched from S3, ensuring consistent comparison.Filter Extraction Helper: Added
get_rule_filter()to extract filter information from rules regardless of whether they use the old or new format.Enhanced Matching Logic: Updated
compare_and_update_configuration()to:rule_idis provided, match by filter (prefix) and rule content (expiration, status, transitions, etc.)rule_idinstead of creating a new oneConsistent Filter Handling: Updated all comparison functions to use the new
get_rule_filter()helper for consistent filter extraction.Changes Made
New Functions
normalize_rule_format(rule)(lines 290-306)get_rule_filter(rule)(lines 310-318)Modified Functions
fetch_rules()(lines 272-286)compare_and_update_configuration()(lines 429-512)get_rule_filter()for consistent filter extractionrule_idis provided but no ID match is found, match by filter and contentcompare_and_remove_rule()(lines 554-567)get_rule_filter()for consistent filter extractionBenefits
Testing
Before Fix
changed: trueeven when rules already existedAfter Fix
rule_idchanged: falsewhen the rule already exists correctlyTest Case
Expected Behavior:
Files Changed
plugins/library/s3_lifecycle.pynormalize_rule_format()functionget_rule_filter()functionfetch_rules()to normalize rulescompare_and_update_configuration()with fallback matching and duplicate removalcompare_and_remove_rule()to use consistent filter extractionImpact
Related Issues
This fix addresses the issue where S3 lifecycle policies with specified
rule_idvalues were being recreated on every playbook execution, leading to rule duplication in S3 buckets.