-
Notifications
You must be signed in to change notification settings - Fork 3.5k
AAP-17690 Inventory variables sourced from git project are not getting deleted after being removed from source #15928
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
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
on_delete=models.CASCADE, | ||
) | ||
group_name = models.CharField(max_length=256) | ||
variables = models.JSONField() # The group variables, including their history. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to ask that someone, like @chrismeyersfsu weigh in on the choice of field type here, JSONField
. There is some baggage with this, and I see json.dumps
being used to save to this field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now I removed the superfluous json.dumps
and json.loads
in front of the JSONField. Thanks for the heads-up, I totally didn't see that.
If @chrismeyersfsu has some concerns regarding the performance impact of a JSONField here, I could switch to a TextField with explicit serialization through json.dumps
and json.loads
.
I had a quick look at the tests, and there's a clear theme that API PATCH requests are getting a 400 editing a simple inventory.
This almost certainly comes from the variables parsing within the serializer. That should be a pretty good clue as to what's going on. Even full integration tests are hitting this, so it's not something weird done directly by a test. |
Codecov ReportAttention: Patch coverage is
✅ All tests successful. No failed tests found. ❌ Your patch status has failed because the patch coverage (97.89%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage. 🚀 New features to boost your workflow:
|
Open topics for this PR:
|
Proposal for product documentation update is available in this comment in the Jira ticket. |
This comment was marked as resolved.
This comment was marked as resolved.
I tested a few things:
|
with open(path, "w") as fp: | ||
fp.write("[all:vars]\n") | ||
fp.write("b=value_b\n") | ||
subprocess.run('git add .; git commit -m "Update variables"', cwd=repo_path, shell=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To say it out loud - it is my intent that running git
commands in a subprocess is in scope for the awx/main/tests/live
tests. For other test suites, something like this would be a blocker, which is why I want to say it. In this space, it's okay to do this stuff.
This was apparent as a use case from the get-go for issues like #13845
path = f"{repo_path}/inventory_var_deleted_in_source.ini" | ||
with open(path, "w") as fp: | ||
fp.write("[all:vars]\n") | ||
fp.write("b=value_b\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting method. I don't mean to criticize how you solved this problem, but I do want to share how I approached the same problem earlier.
https://github.com/ansible/test-playbooks/blob/main/inventories/changes.py
By using an inventory script, it's possible to put in dynamic values for either keys or values. In your case, a randomized key will result in the "old" key disappearing in a subsequent update. This can allow doing the same full-integration test without needing to run git commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look into that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't aware that I can use script-generated inventory files here. Interesting approach, but I guess we cannot preserve state between subsequent calls to such a script. The challenge would be to know what to assert in the test function when we use, e.g., random or timestamp-based variable names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the time being I would like to keep the test method simple, because it does verify the issue the PR is supposed to resolve, and I do not want to delay the merge of this PR longer than necessary.
… handling of None into account
|
…g deleted after being removed from source (ansible#15928) * Delete existing all-group vars on inventory sync (with overwrite-vars=True) instead of merging them. * Implementation of inv var handling with file as db. * Improve serialization to file of inv vars for src update * Include inventory-level variable editing into inventory source update handling * Add group vars to inventory source update handling * Add support for overwrite_vars to new inventory source handling * Persist inventory var history in the database instead of a file. * Remove logging which was needed during development. * Remove further debugging code and improve comments * Move special handling for user edits of variables into serializers * Relate the inventory variable history model to its inventory * Allow for inventory variables to have the value 'None' * Fix KeyError in new inventory variable handling * Add unique-together constraint for new model InventoryGroupVariablesWithHistory * Use only one special invsrc_id for initial update and manual updates * Fix internal server error when creating a new inventory * Print the empty string for a variable with value 'None' * Fix comment which incorrectly states old behaviour * Fix inventory_group_variables_update tests which did not take the new handling of None into account * Allow any type for Ansible-core variable values * Refactor misleading method names * Fix internal server error when savig vars from group form * Remove superfluous json conversion in front of JSONField * Call variable update from create/update instead from validate * Use group_id instead of group_name in model InventoryGroupVariablesWithHistory * Disable new variable update handling for all regular (non-'all') groups * Add live test to verify AAP-17690 (inv var deleted from source) * Add functional tests to verify inventory variables update logic * Fix migration which was corrupted by a rebase * Add a more complex live test and resolve linter complaints * Force overwrite_vars=False for updates from source on all-group * Change behavior with respect to overwrite_vars
SUMMARY
Fixes [AAP-17690] Inventory variables sourced from git project are not getting deleted after being removed from source
The source history for each variable is now preserved, allowing for the updates from source to modify the variables as a user would expect them to behave.
Let A and B be two inventory sources for inventory INV.
A={x:1}, B={x:2} -> sync A -> INV={x:1} -> sync B -> INV={x:2} -> B={} -> sync B -> INV={x:1}
One can see that deleting variable x from source B will not delete x altogether but makes the value from the previous update from source A reappear.
You may think of the source updates as creating an overlay on a variable which covers the previous values. And by deleting a variable from this source and updating from it again will surface the value from the next layer, aka the previous update.
If a inventory source has set
overwrite_vars=True
, an update from this source will prune the history of all variables of this group and keep only this update as the new history.ISSUE TYPE
COMPONENT NAME
AWX VERSION
ADDITIONAL INFORMATION
To reproduce the issue, do the following:
src1.ini:
src2.ini
x: 2
in the Variables field.src2.ini:
Now the issue can be observed:
Since variable x is no longer defined in source B, the inventory should either revert x to the value before the update from B or remove it altogether. But it still shows
x: 2
!