Unexpected behavior modifying non-linear repository versions
If an add/remove operation on a repository results in no changes from the previous version, a new version is not created and the task is completed with no entries in the
created_resources list. This is a great feature, and is an easy to understand behavior.
However, this same behavior can be triggered in another circumstance, one which I believe is far less intuitive and difficult or impossible to handle atomically. In my opinion, this behavior is also difficult to understand without knowledge of the implementation of add/remove operations in Pulp.
If an add/remove operation is attempted based on a previous repository version which will result in the same set of content as the "latest" version at the time of the operation, the same behavior is exhibited: a successful task with no
created_resources - even though the change results in a different set of content from the version on which the operation is specifically based.
The information returned by the operation is then insufficient to differentiate why the operation was "successful but not successful." If I follow-up with a subsequent query for the latest version to compare with my intended contents, I'm racing with another operation creating a new "latest" version.
I can see arguments for and against this latter behavior - refusing to create a new version when one already exists with the desired state. On one hand, it avoids duplicate versions. On the other, it only happens when the matching state happens to be the latest version even though the operation is specifically targeting another base version, and it complicates or eliminates the ability to use the chain of versions as a sort of revision history. Even if I manage to find which version the operation found to be an identical end-state, that state cannot contain the context of which version I'm coming from because it is already based on another version (by design).
Despite these drawbacks, if the behavior is kept, the add/remove operation should be modified to express which already existing repository version it found to match the state that the operation would result in, eliminating the need for subsequent queries and therefore eliminating the opportunity for a race.
From #pulp on Freenode:
cottsay: Happy weekend, everyone. I found some strange behavior related to non-linear repository versioning. It's hard to articulate, so I'm having trouble searching through bugs to find if it is a known issue or not, so I'm hoping someone can provide some insight. The problem occurs when creating a new repository version based on a version other than the latest, which happens to have the same end-state as the latest version.
cottsay: As I understand it, the new version is created by starting with the latest version and adding or removing content to align it was the specified base version: https://github.com/pulp/pulpcore/blob/master/pulpcore/app/models/repository.py#L99-L103
cottsay: If the add/remove operations I'm attempting happen to "undo" those under-the-hood add/remove operations, the operation triggers a "no-op" and no new version is created: https://github.com/pulp/pulpcore/blob/master/pulpcore/app/models/repository.py#L778-L779
cottsay: I can work around the problem by either a) performing a partial updated to get a new "latest version", then finish the update in a second operation (this only works if there are multiple add/remove operations pending) OR b) add extra logic to my add/remove scripting to detect that the target state happens to be the same as the latest version (specifically) and just use that version instead of creating a new one.
ggainey: "if you didn't make a change then a new version isn't created" is considered a feature of Pulp3 - you only get someting new, if there's a change
cottsay: Thanks for the response. I've observed that, and find it desirable. The problem is that the version I'm trying to create IS different from the base version I'm targeting, it just HAPPENS to be the same as the latest version in the repository. If an unrelated operation changes the content in the latest version, the same operation that is triggering the unexpected "no-op" will suddenly succeed in creating a new version.
ggainey: so if you versions 1 - 2 - 3 - 4, and you're creating a new-version based on '2', then 'latest' version will be your new version. If that happens to exactly match 4, you won't get a 5 - but latest will still be what your code resulted in
ggainey: so if you say "make these changes to 2 and give me the resulting version", it wil be 4. If something makes changes to latest, there will be a 5 - but you will still have '4' in hand
cottsay: Conversation is helping me understand, thank you. I find it less than intuitive that I'd need to detect this circumstance specifically. The modify/add-remove operation basically just returns "no change," and doesn't give any indication that the latest version is what I want. If I then go try to fetch the latest version, this introduces a race.
cottsay: I would find the behavior much more expected if the add-remove operation would return the (not) new version that I should be using, even if it didn't create it at that moment.
ggainey: now that sounds like a very valid RFE - nothing worse than code that knows what you want, and won't give it to you!
ggainey: can you open an issue for us please?
Discussion from triage:
<pulpbot> https://pulp.plan.io/issues/6811 <ttereshc> I haven't tested this one but I agree that it's very unexpected for user <dkliban> i read this one earlier. i think the main thing the user wants is that if a new version is not created, the latest version be present in the 'created_resources' list <dkliban> jjeffers has brought this up also <dkliban> jjeffers is adding some special logic to katello for this case <ttereshc> I guess wherever, just there should be a way to show the latest version in that branch <daviddavis> I agree that it would be nice to let the user know somehow that the latest version is unchanged but created_resources seems like a bad match since the version wasn't actually 'created' <ttereshc> yeah, I feel very similar <ttereshc> daviddavis, dkliban, so if the new version is not created, even though it was based on a different base_version, how does one know which version is the previous one? <fao89> I'm not sure if we have to change the code or improve the docs <dkliban> i think this is a story and someone needs to champion it <ttereshc> I agree to covert it to a story <ttereshc> *convert <fao89> !propose other convert to a story <pulpbot> fao89: Proposed for #6811: convert to a story
Please register to edit this issue