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

Fix import bugs #121046

Merged
Merged

Conversation

jportner
Copy link
Contributor

@jportner jportner commented Dec 11, 2021

Resolves #121038 and #122149 and #120312

I combined these three bugfixes into the same PR because they are all touching the same part of the codebase, and I thought it might be harder on everyone to manage three separate PRs.

⚠️ This is best reviewed on a per-commit basis! ⚠️

The first three commits are simple refactoring:

  • ce3b8ed - Refactor unit tests
    Now our mocks are more well-defined and easier to work with. Also this removes one of the annoying jest warnings regarding multiple "mocks/index.ts" files.
  • 76f17de - Refactor getImportIdMapForRetries
    This function should have been in its own module and it was aggravating me, so I went ahead and moved it.
  • 78f2428 - Refactor types
    This renames importIdMap to importStateMap, since I'm changing it to do more than just track what IDs are getting changed (more on that below). It also adds TSdocs so this part of the codebase is less obtuse!

The last three commits are the actual bugfixes. I won't go into too much detail here, the linked issues are quite thorough:

All three of these include updates to unit tests and integration tests as well.

@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 11, 2021
@jportner jportner force-pushed the issue-120312-fix-import-broken-references branch from ce1137f to a152353 Compare December 13, 2021 19:21
@jportner jportner linked an issue Dec 30, 2021 that may be closed by this pull request
@jportner jportner force-pushed the issue-120312-fix-import-broken-references branch from a152353 to f69e2d4 Compare December 30, 2021 16:04
@jportner jportner force-pushed the issue-120312-fix-import-broken-references branch 3 times, most recently from ed9c4e9 to 9e2ca5a Compare January 5, 2022 20:02
Joe Portner added 5 commits January 6, 2022 11:32
Change some mocks for better readability.
Split this function into its own module.
Renamed `importIdMap` to `importStateMap`, changed `id` value to
`destinationId`, and added TSdocs.
@jportner jportner force-pushed the issue-120312-fix-import-broken-references branch from 9e2ca5a to ed3cd39 Compare January 6, 2022 16:34
@jportner jportner force-pushed the issue-120312-fix-import-broken-references branch from ed3cd39 to 96b1583 Compare January 6, 2022 17:27
Copy link
Contributor Author

@jportner jportner left a comment

Choose a reason for hiding this comment

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

Author's notes for reviewers.

const [object] = savedObjects;
if (id !== object.id) {
return {
key: getObjectKey({ type, id }),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm using getObjectKey here instead of a string template ${type}:${id}, and I'm using parseObjectKey further below.

I'm doing this here because of feedback during recent changes that I made to the SOR, where we had a lot of these string templates and we decided we'd prefer to use a common function instead.

There are tons of other ${type}:${id} string templates in the import module, but I opted not to change all of them because this PR already turned out to be bigger than expected 😅 we'll leave that tech debt for another day!

Comment on lines +22 to +26
export interface ImportStateValue {
/**
* This attribute indicates that the object for this entry is *only* a reference, it does not exist in the import file.
*/
isOnlyReference?: boolean;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This isOnlyReference attribute is new. I don't love the name, but I couldn't think of anything better. I'm totally open to suggestions here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't really have anything that much better. isOutboundReference? referencedObjects?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤷 yeah I think the only thing that would make it clearer would be to have a separate state map just for references, but that would add a lot of boilerplate and complexity so I wanted to avoid that.

@@ -8,23 +8,34 @@
import expect from '@kbn/expect';
import { SuperTest } from 'supertest';
import type { Client } from '@elastic/elasticsearch';
import type { SavedObjectReference } from 'src/core/server';
import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases';
import { SPACES } from '../lib/spaces';
import { expectResponses, getUrlPrefix, getTestTitle } from '../lib/saved_object_test_utils';
import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types';

export interface ImportTestDefinition extends TestDefinition {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The import and resolveImportErrors integration tests were designed to import a mixture of objects that don't exist yet, with objects that already exist. This would generate conflict errors, and the destination objects would need to be overwritten. Each suite exercises three different scenarios:

  1. createNewCopies: false, overwrite: false
    image
  2. createNewCopies: false, overwrite: true
    image
  3. createNewCopies: true, overwrite: false`
    image

The problem is there is another type of error that can occur, a "missing references" error, that originates from the validateReferences module. We never had tests for this before, and I thought it would be prudent to add tests for this now, since we need to make assertions that Kibana is correctly matching origins for references anyway.

Unfortunately, these test suites needed some significant refactoring to make this happen. There are a lot of ways to skin this cat, but I tried to make the most minimal changes possible. I think there is a lot of room for improvement, but I didn't want this PR to be any bigger than it already is.

Comment on lines +75 to +76
export const SPECIAL_TEST_CASES: Record<string, ImportTestCase> = Object.freeze({
HIDDEN,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We already treated the "HIDDEN" test case as a special case before, I'm just making that clearer now.

@jportner jportner marked this pull request as ready for review January 6, 2022 17:41
@jportner jportner requested review from a team as code owners January 6, 2022 17:41
Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

Last commit was sure fun to review, but I think it's LGTM overall.

We really need to cleanup and refactor our FTR tests related to import/export though, it's becoming VERY hard to review this part of the code.

Copy link
Contributor

@thomheymann thomheymann left a comment

Choose a reason for hiding this comment

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

Verified #121038, #122149, and #120312 locally and working as defined.

As discussed though I worry about the complexity of the import and copy functionality.

There are a lot of edge cases which did not behave the way I would have expect in order to preserve the (accidental) legacy behaviour:

  • There are situations now where depending on the type of saved objects or the number of references those saved objects have, the "overwrite existing saved objects" setting gets ignored for some of the imported objects but not for others
  • Similarly the "resolve conflicts manually" setting gets ignored where users are asked to resolve conflicts themselves for some saved objects even though they selected to automatically resolve conflicts. If that's the case we probably shouldn't provide this option at all.
  • There are also situations where conflicts are ignored when index patterns are missing causing duplicate saved objects despite "overwrite existing saved objects" being selected.

I appreciate that we want to have as few breaking changes as possible but I find all of the above quite problematic from a user and maintenance perspective since it's almost impossible to predict what is actually going to happen on import.

The sheer number of scenarios and user flows also means we end up with a lot of code complexity and ultimately these types of bugs and edge cases.

I think it would be good to try and simplify this functionality in the future.

@rudolf
Copy link
Contributor

rudolf commented Jan 12, 2022

@thomheymann I completely agree. We had some discussions in September for how we could solve this and we were mostly aligned on the approach but unfortunately we haven't made any further progress on this see #91615 (comment) I think it would be useful for you to add your comment to that issue.

@jportner
Copy link
Contributor Author

@elasticmachine merge upstream

@jportner
Copy link
Contributor Author

Thanks all, I also agree this is way too complex and there are too many edge cases. More motivation for us to actually solve this and do away with this import API once and for all.

@jportner jportner enabled auto-merge (squash) January 12, 2022 17:54
@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

@jportner jportner merged commit 116d74a into elastic:main Jan 12, 2022
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Jan 12, 2022
(cherry picked from commit 116d74a)
@kibanamachine
Copy link
Contributor

💚 All backports created successfully

Status Branch Result
8.0

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Jan 12, 2022
(cherry picked from commit 116d74a)

Co-authored-by: Joe Portner <[email protected]>
@jportner jportner deleted the issue-120312-fix-import-broken-references branch January 19, 2022 20:45
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
6 participants