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

Prevent endless loop for saved object migrations #120146

Merged
merged 4 commits into from
Dec 3, 2021

Conversation

jportner
Copy link
Contributor

@jportner jportner commented Dec 1, 2021

Resolves #120129.

This changes the DocumentMigrator behavior so that reference transforms are not accidentally skipped when an object has a higher migrationVersion than its coreMigrationVersion.

I'm labeling this as release_note:skip because it's fixing an unreleased bug.

@jportner jportner added v8.0.0 release_note:skip Skip the PR/issue when compiling release notes auto-backport Deprecated - use backport:version if exact versions are needed v8.1.0 labels Dec 1, 2021
@jportner jportner requested a review from a team as a code owner December 1, 2021 18:24
Comment on lines 757 to 760
if (currentVersion && Semver.gt(currentVersion, version)) {
if (currentVersion && Semver.gt(currentVersion, version) && transformType !== 'reference') {
// the previous transform function increased the object's migrationVersion; break out of the loop
break;
}
Copy link
Contributor Author

@jportner jportner Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes the bug at hand, but maybe we want to change more than this.

I mentioned in the linked issue and I will mention again here, we had a conversation about this last year: #80945 (comment)

The comment chain on that PR is very long, but here's a screenshot of the discussion in question:

image

And here is the commit that my comment linked to: e27e6be


SO:

  1. Technically you can define a "migration" transform that skips your object's "conversion" transform. It's not a problem that we realistically have to worry about, but maybe we want to prevent that from happening?
  2. While we're at it, maybe we want to reconsider this whole idea of allowing "leapfrog" migrations. AFAIK it was supported in the original DocumentMigrator implementation but it has never been used by consumers. We already had unit tests for it, true, but in hindsight it seems to add unnecessary complexity for a feature that no consumers are using (that we are aware of).

So, maybe we should just rip out these 3 lines of code and modify the tests accordingly. WDYT?

Edit: To make it fully clear, I think we should rip this out completely. I just wanted to submit the PR with the minimal fix first so we all have the right context.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this code is really hard to follow so any complexity we can remove would be worth it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I will make additional changes tomorrow to that effect

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in 060dff5.

I noticed some comments at the top of the document that mention that migration functions can increase the migrationVersion, but cannot decrease it. I changed those comments accordingly and added an explicit disclaimer in our dev docs that changing migrationVersion, type, and id fields is not supported.

I noticed there is already an assertNoDowngrades validation function that checks to see if a consumer has decreased the migrationVersion and throws an error:

function assertNoDowngrades(
doc: SavedObjectUnsanitizedDoc,
migrationVersion: SavedObjectsMigrationVersion,
prop: string,
version: string
) {
const docVersion = doc.migrationVersion;
if (!docVersion) {
return;
}
const downgrade = Object.keys(migrationVersion).find(
(k) => !docVersion.hasOwnProperty(k) || Semver.lt(docVersion[k], migrationVersion[k])
);
if (downgrade) {
throw new Error(
`Migration "${prop} v ${version}" attempted to ` +
`downgrade "migrationVersion.${downgrade}" from ${migrationVersion[downgrade]} ` +
`to ${docVersion[downgrade]}.`
);
}
}

This is good to keep, because decreasing the migrationVersion could cause an infinite loop.

I didn't add validation to check for an increased migrationVersion, my reasoning is:

  • The impact is low -- a migration function that increases the migrationVersion simply won't work as intended, e.g., it won't "leapfrog" other transforms
  • I want to reduce complexity and testing burden
  • We never explicitly stated in our dev docs that we supported increasing the migrationVersion, and now we are explicitly stating that we don't support it

But if you think I should add validation anyway, I'll do it, just let me know.

@jportner jportner requested a review from rudolf December 2, 2021 19:46
@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@rudolf
Copy link
Contributor

rudolf commented Dec 3, 2021

Thanks for taking this one! ❤️

@jportner jportner merged commit 89b1f90 into elastic:main Dec 3, 2021
@jportner jportner deleted the issue-120129-endless-migration-loop branch December 3, 2021 13:42
jportner added a commit to jportner/kibana that referenced this pull request Dec 3, 2021
jportner added a commit that referenced this pull request Dec 3, 2021
…0350)

* Prevent endless loop for saved object migrations (#120146)

* Fix invalid saved objects

* Fix more invalid saved objects
TinLe pushed a commit to TinLe/kibana that referenced this pull request Dec 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Deprecated - use backport:version if exact versions are needed release_note:skip Skip the PR/issue when compiling release notes v8.0.0 v8.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Saved object migrations can get into an endless loop
3 participants