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

[SIEM] Migrating frontend services to NP #52783

Merged
merged 40 commits into from
Dec 20, 2019

Conversation

rylnd
Copy link
Contributor

@rylnd rylnd commented Dec 11, 2019

Summary

This is a first pass at migrating some services over to their new platform equivalents.
Partially addresses #45831.

Removed legacy imports:

  • ui/index_patterns
  • ui/documentation_links
  • ui/chrome
    • settings client
    • getBasePath
    • helpExtension
    • breadcrumbs
    • getXsrfToken
  • ui/registry/feature_catalogue

Other changes:

  • replaced useKibanaUiSetting hook with kibana_react's useUiSetting and useUiSetting$
  • replaced useKibanaCore and useKibanaPlugins with kibana_react's useKibana
  • added mocks for kibana_react

Checklist

Use strikethroughs to remove checklist items you don't feel are applicable to this PR.

For maintainers

@rylnd rylnd added Feature:New Platform release_note:skip Skip the PR/issue when compiling release notes v7.6.0 labels Dec 11, 2019
@rylnd rylnd force-pushed the siem_ui_new_platform_services branch 2 times, most recently from 1161d5f to bdccb3b Compare December 16, 2019 15:36
rylnd added 25 commits December 16, 2019 11:54
We'd already brought in the new interface in a previous commit; this was
just used as an unnecessary type assertion.
In most instances, this meant using the useContext hook with our NP core
context.

This also updates our mocks to leverage the factory so graciously
provided by platform.

There are a few failing tests, mostly due to links being previously
undefined in tests.
These are not picked up by jest; calling
jest.mock('lib/compose/kibana_core') has the same effect whether or not
these files exist.
The timeline tests are the last place we're explicitly mocking
useKibanaCore; removing the mocks cause tests to hang. I think  hey're
relying on the side effects of importing the mock/ui_settings file, but
I'll figure that out next.
These have to be evaluated immediately so that we always return the
same core object. Otherwise we get stuck in a loop between
render/useEffect/setState due to the savedObjects client being different
on each invocation.
Previously, we were invoking it any time someone called `useKibanaCore`,
getting a new object back each time. This both caused some bugs (looping
with useEffect) and was not representative of how the actual hook
worked.

This also moves that invokation into the mock function, along with
shaping the mocked module so that we don't have to do it in every call
to jest.mock.
We're re-exporting these locally to have more control around mocking
them (until platform implements that).

This breaks everything that was using the old mocks. Will fix.
Instead of our homegrown hooks we can use these utilities instead.

Unfortunately kibana_react doesn't yet have mocks, so we had to implement
that ourselves. Luckily, we already had local mocks for the settings
service. This migrates to a the new format. For clarity and consistency,
we also re-export new platform's mocks here and use them to populate our
kibana_react mocks.

We started by migrating the UiSettings service to new platform, and let
that drive the rest. With the mocks in place for kibana_react, removing
the usage of useKibanaCore was a natural step as well.

The next step is removing the usage of chrome.getUiSettingsClient with
our useUiSetting$ hook, and with that (and maybe some config setup; I'm
seeing errors at runtime), we should be ready to start migrating other
services.
We were previously returning a new copy any time e.g. useKibana was
called, which is not the contract that consumers are expecting. and in
fact caused looping with components employing useEffect etc.
We're now using kibana_react fully.
Remaining failures are either due to a date format issue, or something
being rendered differently. Those are up next.

Still haven't touched use of chrome.getUiSettingsClient, that's after.
* mocks missing UI Setting (DEFAULT_TIMEZONE_BROWSER) which is required
by our formatted_date utilities
* mock timepicker ranges in the one test that uses it (SuperDatePicker)
Since our TestProvider now mocks new platform, the only tests that
should need to mock uiSettings related stuff (e.g. timezone preferences)
would be the tests that (directly or no) use kibana_react to get it.
* adds a mock for the non-observable useUiSetting
* removes the unmockable HOC withKibana
We're opting for the non-observable behavior here because I believe
that's more analagous.

There are a few remaining usages in non-react code.

Tests are still using the mocks, those'll be removed next.
Now that we're not using this hook there's no need for the mocks. Tests
are green.
We're now using the ones provided by kibana_react.
React was kind enough to remind me that I can't put hooks in classes.
Whoops.
The service claims not to know about these settings we're retrieving.
Until I can figure out where they should come from, we're going to
initialize them with what seem to be the defaults at plugin
initialization.
These have now been replaced with kibana_react's equivalents.
This is one of the few places where we're using another plugin, which
are not present in the default typings due to their opt-in nature.
The indexPattern we get back is actually an array. The endpoint seems to
handle this just fine (at least, it doesn't blow up), but once we
started retrieving a typed value this error surfaced.
Rather than having to type this on each invocation. This requires us to
define which plugins we depend on, which is a good thing.

describe('FirstLastSeen Component', () => {
const firstSeen = 'Apr 8, 2019 @ 16:09:40.692';
const lastSeen = 'Apr 8, 2019 @ 18:35:45.064';

// Suppress warnings about "react-apollo" until we migrate to apollo@3
/* eslint-disable no-console */
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we are the only ones left with react-apollo at this point :-)

I see some left overs in Infra but I would imagine we are going to take over ownership unless another plugin starts using it.

@@ -73,7 +77,7 @@ class AuthenticationsOverTimeComponentQuery extends QueryTemplate<
from: startDate!,
to: endDate!,
},
defaultIndex: chrome.getUiSettingsClient().get(DEFAULT_INDEX_KEY),
defaultIndex: kibana.services.uiSettings.get<string[]>(DEFAULT_INDEX_KEY),
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Nice to see the new API. Like it takes a <string[]> as a template.

Copy link
Contributor Author

@rylnd rylnd Dec 17, 2019

Choose a reason for hiding this comment

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

What do you think about exporting "bound" generic types internally?

const indexPatterns = useUiSetting<string[]>(DEFAULT_INDEX_KEY);
// vs
const indexPatterns = useIndexPatterns();

In both cases indexPatterns would be typed as string[]. I already did that for our own useKibana hook to reduce boilerplate, and I think it makes sense for these common settings that we retrieve all over the place, too (DEFAULT_INDEX_KEY, DEFAULT_KBN_VERSION).

Copy link
Contributor

@FrankHassanabad FrankHassanabad Dec 18, 2019

Choose a reason for hiding this comment

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

I think the bound version const indexPatterns = useIndexPatterns(); reads much better

Copy link
Contributor Author

Choose a reason for hiding this comment

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

NB this new typed API has so far surfaced one type error that I was excited might be a bug, but the client/endpoint that ultimately use it seem to handle the array interpolation just fine? 🤷‍♂

Also, we don't seem to have consistent jargon for this concept of an array of index patterns: it's mainly called defaultIndex(not plural?), but I've also seen defaultIndexPattern, indicesConfig, etc. Is the lack of pluralization due to the fuzziness of the elastic API? Is an array of index patterns also an index pattern?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's influenced by the ES API which in most cases takes a variable called index which is an array.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FYI: It looks like this broad context might be replaced by more declarative hooks in the near future, so wrapping our current usage is definitely the way to go given our simple use case.

@@ -49,7 +49,7 @@ const IpOverviewComponentQuery = React.memo<IpOverviewProps & IpOverviewReduxPro
sourceId,
filterQuery: createFilter(filterQuery),
ip,
defaultIndex: chrome.getUiSettingsClient().get(DEFAULT_INDEX_KEY),
defaultIndex: useUiSetting<string[]>(DEFAULT_INDEX_KEY),
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there two different ways of doing this?

I see both:

defaultIndex: kibana.services.uiSettings.get<string[]>(DEFAULT_INDEX_KEY),

and

useUiSetting<string[]>(DEFAULT_INDEX_KEY),

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like maybe one is a React Hook function and the other is just a plain API call for non-tsx React code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They both reference the same context provider under the hood! The former's an HOC prop (via withKibana) used for class components, and the latter is a hook used by function components.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@FrankHassanabad you bring up a good point, though: I'm trying to pull as much of this as possible from the react context and avoiding grabbing state (e.g. chrome.getUiSettingsClient) outside of react/platform's control.

@@ -53,7 +54,7 @@ export interface UsersComponentReduxProps {
sort: UsersSortField;
}

type UsersProps = OwnProps & UsersComponentReduxProps;
type UsersProps = OwnProps & UsersComponentReduxProps & WithKibanaProps;
Copy link
Contributor

Choose a reason for hiding this comment

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

That's an interesting type & WithKibanaProps; That's nice we have more access to Kibana Props now 👍

Copy link
Contributor

@FrankHassanabad FrankHassanabad left a comment

Choose a reason for hiding this comment

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

Checked it out, tested it, looked through it. Soo many good things in here to reject it over anything small in my opinion so I give this an early exclusive LGTM from myself. I understand there is probably a few more questions from others in their expertise.

I did test out some of the detection engine rules and everything looks ok there as well.

 Conflicts:
	x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx
	x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx
	x-pack/legacy/plugins/siem/public/pages/network/network.tsx
@@ -44,7 +40,7 @@ const StartApp: FC<AppFrontendLibs> = memo(libs => {
const store = createStore(undefined, libs$.pipe(pluck('apolloClient')));
Copy link
Contributor Author

@rylnd rylnd Dec 17, 2019

Choose a reason for hiding this comment

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

@rudolf we have a few uses of chrome.getUiSettingsClient remaining in functions that we use to populate part of our initial redux state (time filter preferences, etc.). Here's how we're thinking of tackling that, just wanted a sanity check from your end:

  1. Define the setup() method of our plugin
  2. Fetch those UI settings in setup, and do some merging with the rest of our static initial state to create our store object
  3. Pass that store to the store Provider (via a private plugin property?) during the start() phase

Copy link
Contributor

Choose a reason for hiding this comment

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

Step 1 & 2 sound fine, however step 3 is a bit off. Registering applications is done during setup via the core.application.register API. You'll be able to use your initial store right there without using a private property on your plugin class.

 Conflicts:
	x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx
	x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx
	x-pack/legacy/plugins/siem/public/pages/network/network.tsx
Copy link
Contributor

@joshdover joshdover left a comment

Choose a reason for hiding this comment

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

Because you're already using Redux, I heavily advise not using the KibanaContextProvider pattern and instead managing all state through Redux abstractions. Not to say this way isn't viable, it's just going to be rough from a maintenance perspective.

See this discussion for more context: #53029 (comment)

Comment on lines 41 to 42
this.chrome.setRootTemplate(template);
const checkForRoot = () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe you can replace all this code with the NP mounting mechanism in setup: core.application.register

@@ -44,7 +40,7 @@ const StartApp: FC<AppFrontendLibs> = memo(libs => {
const store = createStore(undefined, libs$.pipe(pluck('apolloClient')));
Copy link
Contributor

Choose a reason for hiding this comment

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

Step 1 & 2 sound fine, however step 3 is a bit off. Registering applications is done during setup via the core.application.register API. You'll be able to use your initial store right there without using a private property on your plugin class.

public start(core: StartCore, plugins: StartPlugins) {
// TODO(rylnd): once we're on NP, we can populate version from env.packageInfo
core.uiSettings.set(DEFAULT_KBN_VERSION, '8.0.0');
core.uiSettings.set(DEFAULT_TIMEZONE_BROWSER, 'UTC');
Copy link
Contributor

Choose a reason for hiding this comment

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

What error are you getting? Why do you set these settings here? Did you mean to use core.uiSettings.get?

We were previously getting errors due to these values not being known to
the client, but it looks like that was either fixed upstream, or a
temporary issue caused by some improper context setup.
Let's leave JSX out of it.
@rylnd
Copy link
Contributor Author

rylnd commented Dec 19, 2019

Because you're already using Redux, I heavily advise not using the KibanaContextProvider pattern and instead managing all state through Redux abstractions. Not to say this way isn't viable, it's just going to be rough from a maintenance perspective.

See this discussion for more context: #53029 (comment)

@joshdover yep, I've been watching that conversation and realize that the context provider isn't a good long-term solution (as evidenced by all the simple components that we're still mocking).

Do you have a more complete example of using redux to accomplish all this? Things I'm wondering about:

  • How would a component access e.g. the saved queries service?
  • How would a component subscribe to UI Settings changes?

A call would be great to make sure that we're on the same page as platform, too.

That being said, are you okay with merging this in the meantime? I've already started on a PR that fleshes out a setup step and removes a lot of the cruft you mentioned, but this PR mainly just removes our custom providers/hooks/mocks.

@joshdover
Copy link
Contributor

Do you have a more complete example of using redux to accomplish all this? Things I'm wondering about:

No examples that I'm aware of but here's the flow I imagined...

  • How would a component access e.g. the saved queries service?

Components wouldn't access saved queries directly, they'd dispatch a GET_SAVED_QUERY actionCreator which would use redux-thunk or redux-saga to do the actual fetching, then dispatch a SET_SAVED_QUERY action with the details needed. A reducer would then handle updating the Redux store, propagating changes to React components.

  • How would a component subscribe to UI Settings changes?

Similarly, a subscription could be set up with the uiSettings APIs directly, and when the settings change, dispatch an appropriate action to the Redux store. A reducer would be set up to handle these actions and compute the next state of the store.

import { combineLatest } from 'rxjs';

combineLatest(
  uiSettings.get$('setting1'),
  uiSettings.get$('setting2')
).subscribe(([setting1, setting2]) => {
  store.dispatch({
    type: 'UPDATE_SETTINGS',
    setting1,
    setting2
  });
});

@joshdover
Copy link
Contributor

That being said, are you okay with merging this in the meantime? I've already started on a PR that fleshes out a setup step and removes a lot of the cruft you mentioned, but this PR mainly just removes our custom providers/hooks/mocks.

Yep, no opposition here, it's your plugin. Just trying to point out ways to make refactoring easier in the future.

@rylnd
Copy link
Contributor Author

rylnd commented Dec 19, 2019

Thanks for the help @joshdover, it's much appreciated.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

History

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

@rylnd rylnd merged commit 02278ed into elastic:master Dec 20, 2019
@rylnd rylnd deleted the siem_ui_new_platform_services branch December 20, 2019 00:41
@spalger
Copy link
Contributor

spalger commented Dec 20, 2019

This is somehow breaking master, reverting for now

spalger pushed a commit that referenced this pull request Dec 20, 2019
spalger pushed a commit that referenced this pull request Dec 20, 2019
rylnd added a commit to rylnd/kibana that referenced this pull request Dec 20, 2019
* Remove legacy index_patterns import

We'd already brought in the new interface in a previous commit; this was
just used as an unnecessary type assertion.

* Update snapshots following new docLink mocks

* Remove unused manual mocks

These are not picked up by jest; calling
jest.mock('lib/compose/kibana_core') has the same effect whether or not
these files exist.

* WIP: Use kibana core mock everywhere we're doing it manually

The timeline tests are the last place we're explicitly mocking
useKibanaCore; removing the mocks cause tests to hang. I think  hey're
relying on the side effects of importing the mock/ui_settings file, but
I'll figure that out next.

* Replace ui/documentation_links with core NP service

In most instances, this meant using the useContext hook with our NP core
context.

This also updates our mocks to leverage the factory so graciously
provided by platform.

There are a few failing tests, mostly due to links being previously
undefined in tests.

* Use new mocks on timeline test that doesn't hang

The rest of these do, though.

* Remove remaining uses of mockUiSettings in useKibanaCore mocks

These have to be evaluated immediately so that we always return the
same core object. Otherwise we get stuck in a loop between
render/useEffect/setState due to the savedObjects client being different
on each invocation.

* Invoke platform's mock factory at mock time

Previously, we were invoking it any time someone called `useKibanaCore`,
getting a new object back each time. This both caused some bugs (looping
with useEffect) and was not representative of how the actual hook
worked.

This also moves that invokation into the mock function, along with
shaping the mocked module so that we don't have to do it in every call
to jest.mock.

* WIP: migrating to use kibana_react's provider and helpers

We're re-exporting these locally to have more control around mocking
them (until platform implements that).

This breaks everything that was using the old mocks. Will fix.

* WIP: Migrating to use kibana_react

Instead of our homegrown hooks we can use these utilities instead.

Unfortunately kibana_react doesn't yet have mocks, so we had to implement
that ourselves. Luckily, we already had local mocks for the settings
service. This migrates to a the new format. For clarity and consistency,
we also re-export new platform's mocks here and use them to populate our
kibana_react mocks.

We started by migrating the UiSettings service to new platform, and let
that drive the rest. With the mocks in place for kibana_react, removing
the usage of useKibanaCore was a natural step as well.

The next step is removing the usage of chrome.getUiSettingsClient with
our useUiSetting$ hook, and with that (and maybe some config setup; I'm
seeing errors at runtime), we should be ready to start migrating other
services.

* Bind a copy of kibana at mock creation

We were previously returning a new copy any time e.g. useKibana was
called, which is not the contract that consumers are expecting. and in
fact caused looping with components employing useEffect etc.

* Remove internal context providers and last usage

We're now using kibana_react fully.

* Fix tests failing due to wrong mocks

Remaining failures are either due to a date format issue, or something
being rendered differently. Those are up next.

Still haven't touched use of chrome.getUiSettingsClient, that's after.

* Fix test failures related to date formatting

* mocks missing UI Setting (DEFAULT_TIMEZONE_BROWSER) which is required
by our formatted_date utilities
* mock timepicker ranges in the one test that uses it (SuperDatePicker)

* Remove unnecessary and/or redundant mocks

Since our TestProvider now mocks new platform, the only tests that
should need to mock uiSettings related stuff (e.g. timezone preferences)
would be the tests that (directly or no) use kibana_react to get it.

* Refactor kibana_react mocks

* adds a mock for the non-observable useUiSetting
* removes the unmockable HOC withKibana

* Replace usage of chrome.getUiSettingsClient with useUiSetting

We're opting for the non-observable behavior here because I believe
that's more analagous.

There are a few remaining usages in non-react code.

Tests are still using the mocks, those'll be removed next.

* Remove ui_settings mocks

Now that we're not using this hook there's no need for the mocks. Tests
are green.

* Remove siem's UI settings hook

We're now using the ones provided by kibana_react.

* Use withKibana HOC on our component classes

React was kind enough to remind me that I can't put hooks in classes.
Whoops.

* Set defaults for some unknown UI settings

The service claims not to know about these settings we're retrieving.
Until I can figure out where they should come from, we're going to
initialize them with what seem to be the defaults at plugin
initialization.

* Remove old hooks

These have now been replaced with kibana_react's equivalents.

* Fix type error on usage of useKibana hook

This is one of the few places where we're using another plugin, which
are not present in the default typings due to their opt-in nature.

* Fix type error on ML call

The indexPattern we get back is actually an array. The endpoint seems to
handle this just fine (at least, it doesn't blow up), but once we
started retrieving a typed value this error surfaced.

* Export a 'bound' version of the useKibana function

Rather than having to type this on each invocation. This requires us to
define which plugins we depend on, which is a good thing.

* Instantiate our mock function

We aren't using these right now I didn't notice, but that wasn't the
right reference.

* Fix test that relies on unmocked service

Our QueryBar component relies very (very, very) indirectly on a storage
service that does not exist in New Platform, nor its corresponding
mocks. To get it passing for now, we're just gonna pretend like it's
there.

* Remove use of ui/chrome in our charts

Replaces with hooks that accomplish the same.

* Remove last use of chrome.getUiSettingsClient

This function is itself a hook, so we should be good here.

* Remove unnecessary non-null assertions

Now that we're using our typed version of the useKibana hook, typescript
knows that these services will be available (once we actually enforce
that in our kibana.json, of course).

* Fix chart tests

These rely on a kibana hook now, so we need to mock it out for these
renders lest we blow up when the context isn't there.

* Replace missing mock

I deleted this in a previous commit, thinking it unneeded.
However, getHostDetailsBreadcrumbs ultimately asks for some
default date parameters for the timerange boundaries.

* Add back tests for our theming hook

* Style: cleanup

* Remove unneeded default UI Settings values

We were previously getting errors due to these values not being known to
the client, but it looks like that was either fixed upstream, or a
temporary issue caused by some improper context setup.

* Simplify kibana_react mocks

Let's leave JSX out of it.

Co-authored-by: Elastic Machine <[email protected]>
rylnd added a commit that referenced this pull request Dec 20, 2019
* [SIEM] Migrating frontend services to NP (#52783)

* Remove legacy index_patterns import

We'd already brought in the new interface in a previous commit; this was
just used as an unnecessary type assertion.

* Update snapshots following new docLink mocks

* Remove unused manual mocks

These are not picked up by jest; calling
jest.mock('lib/compose/kibana_core') has the same effect whether or not
these files exist.

* WIP: Use kibana core mock everywhere we're doing it manually

The timeline tests are the last place we're explicitly mocking
useKibanaCore; removing the mocks cause tests to hang. I think  hey're
relying on the side effects of importing the mock/ui_settings file, but
I'll figure that out next.

* Replace ui/documentation_links with core NP service

In most instances, this meant using the useContext hook with our NP core
context.

This also updates our mocks to leverage the factory so graciously
provided by platform.

There are a few failing tests, mostly due to links being previously
undefined in tests.

* Use new mocks on timeline test that doesn't hang

The rest of these do, though.

* Remove remaining uses of mockUiSettings in useKibanaCore mocks

These have to be evaluated immediately so that we always return the
same core object. Otherwise we get stuck in a loop between
render/useEffect/setState due to the savedObjects client being different
on each invocation.

* Invoke platform's mock factory at mock time

Previously, we were invoking it any time someone called `useKibanaCore`,
getting a new object back each time. This both caused some bugs (looping
with useEffect) and was not representative of how the actual hook
worked.

This also moves that invokation into the mock function, along with
shaping the mocked module so that we don't have to do it in every call
to jest.mock.

* WIP: migrating to use kibana_react's provider and helpers

We're re-exporting these locally to have more control around mocking
them (until platform implements that).

This breaks everything that was using the old mocks. Will fix.

* WIP: Migrating to use kibana_react

Instead of our homegrown hooks we can use these utilities instead.

Unfortunately kibana_react doesn't yet have mocks, so we had to implement
that ourselves. Luckily, we already had local mocks for the settings
service. This migrates to a the new format. For clarity and consistency,
we also re-export new platform's mocks here and use them to populate our
kibana_react mocks.

We started by migrating the UiSettings service to new platform, and let
that drive the rest. With the mocks in place for kibana_react, removing
the usage of useKibanaCore was a natural step as well.

The next step is removing the usage of chrome.getUiSettingsClient with
our useUiSetting$ hook, and with that (and maybe some config setup; I'm
seeing errors at runtime), we should be ready to start migrating other
services.

* Bind a copy of kibana at mock creation

We were previously returning a new copy any time e.g. useKibana was
called, which is not the contract that consumers are expecting. and in
fact caused looping with components employing useEffect etc.

* Remove internal context providers and last usage

We're now using kibana_react fully.

* Fix tests failing due to wrong mocks

Remaining failures are either due to a date format issue, or something
being rendered differently. Those are up next.

Still haven't touched use of chrome.getUiSettingsClient, that's after.

* Fix test failures related to date formatting

* mocks missing UI Setting (DEFAULT_TIMEZONE_BROWSER) which is required
by our formatted_date utilities
* mock timepicker ranges in the one test that uses it (SuperDatePicker)

* Remove unnecessary and/or redundant mocks

Since our TestProvider now mocks new platform, the only tests that
should need to mock uiSettings related stuff (e.g. timezone preferences)
would be the tests that (directly or no) use kibana_react to get it.

* Refactor kibana_react mocks

* adds a mock for the non-observable useUiSetting
* removes the unmockable HOC withKibana

* Replace usage of chrome.getUiSettingsClient with useUiSetting

We're opting for the non-observable behavior here because I believe
that's more analagous.

There are a few remaining usages in non-react code.

Tests are still using the mocks, those'll be removed next.

* Remove ui_settings mocks

Now that we're not using this hook there's no need for the mocks. Tests
are green.

* Remove siem's UI settings hook

We're now using the ones provided by kibana_react.

* Use withKibana HOC on our component classes

React was kind enough to remind me that I can't put hooks in classes.
Whoops.

* Set defaults for some unknown UI settings

The service claims not to know about these settings we're retrieving.
Until I can figure out where they should come from, we're going to
initialize them with what seem to be the defaults at plugin
initialization.

* Remove old hooks

These have now been replaced with kibana_react's equivalents.

* Fix type error on usage of useKibana hook

This is one of the few places where we're using another plugin, which
are not present in the default typings due to their opt-in nature.

* Fix type error on ML call

The indexPattern we get back is actually an array. The endpoint seems to
handle this just fine (at least, it doesn't blow up), but once we
started retrieving a typed value this error surfaced.

* Export a 'bound' version of the useKibana function

Rather than having to type this on each invocation. This requires us to
define which plugins we depend on, which is a good thing.

* Instantiate our mock function

We aren't using these right now I didn't notice, but that wasn't the
right reference.

* Fix test that relies on unmocked service

Our QueryBar component relies very (very, very) indirectly on a storage
service that does not exist in New Platform, nor its corresponding
mocks. To get it passing for now, we're just gonna pretend like it's
there.

* Remove use of ui/chrome in our charts

Replaces with hooks that accomplish the same.

* Remove last use of chrome.getUiSettingsClient

This function is itself a hook, so we should be good here.

* Remove unnecessary non-null assertions

Now that we're using our typed version of the useKibana hook, typescript
knows that these services will be available (once we actually enforce
that in our kibana.json, of course).

* Fix chart tests

These rely on a kibana hook now, so we need to mock it out for these
renders lest we blow up when the context isn't there.

* Replace missing mock

I deleted this in a previous commit, thinking it unneeded.
However, getHostDetailsBreadcrumbs ultimately asks for some
default date parameters for the timerange boundaries.

* Add back tests for our theming hook

* Style: cleanup

* Remove unneeded default UI Settings values

We were previously getting errors due to these values not being known to
the client, but it looks like that was either fixed upstream, or a
temporary issue caused by some improper context setup.

* Simplify kibana_react mocks

Let's leave JSX out of it.

Co-authored-by: Elastic Machine <[email protected]>

* Update references to now-deleted hooks

These hooks were deleted on a recent branch, but new usages were merged
to master in the meantime.

* Fix remaining uses of hooks/chrome that were not merge conflicts

* Use HOC on class component

Co-authored-by: Elastic Machine <[email protected]>
rylnd added a commit that referenced this pull request Dec 20, 2019
* [SIEM] Migrating frontend services to NP (#52783)

* Remove legacy index_patterns import

We'd already brought in the new interface in a previous commit; this was
just used as an unnecessary type assertion.

* Update snapshots following new docLink mocks

* Remove unused manual mocks

These are not picked up by jest; calling
jest.mock('lib/compose/kibana_core') has the same effect whether or not
these files exist.

* WIP: Use kibana core mock everywhere we're doing it manually

The timeline tests are the last place we're explicitly mocking
useKibanaCore; removing the mocks cause tests to hang. I think  hey're
relying on the side effects of importing the mock/ui_settings file, but
I'll figure that out next.

* Replace ui/documentation_links with core NP service

In most instances, this meant using the useContext hook with our NP core
context.

This also updates our mocks to leverage the factory so graciously
provided by platform.

There are a few failing tests, mostly due to links being previously
undefined in tests.

* Use new mocks on timeline test that doesn't hang

The rest of these do, though.

* Remove remaining uses of mockUiSettings in useKibanaCore mocks

These have to be evaluated immediately so that we always return the
same core object. Otherwise we get stuck in a loop between
render/useEffect/setState due to the savedObjects client being different
on each invocation.

* Invoke platform's mock factory at mock time

Previously, we were invoking it any time someone called `useKibanaCore`,
getting a new object back each time. This both caused some bugs (looping
with useEffect) and was not representative of how the actual hook
worked.

This also moves that invokation into the mock function, along with
shaping the mocked module so that we don't have to do it in every call
to jest.mock.

* WIP: migrating to use kibana_react's provider and helpers

We're re-exporting these locally to have more control around mocking
them (until platform implements that).

This breaks everything that was using the old mocks. Will fix.

* WIP: Migrating to use kibana_react

Instead of our homegrown hooks we can use these utilities instead.

Unfortunately kibana_react doesn't yet have mocks, so we had to implement
that ourselves. Luckily, we already had local mocks for the settings
service. This migrates to a the new format. For clarity and consistency,
we also re-export new platform's mocks here and use them to populate our
kibana_react mocks.

We started by migrating the UiSettings service to new platform, and let
that drive the rest. With the mocks in place for kibana_react, removing
the usage of useKibanaCore was a natural step as well.

The next step is removing the usage of chrome.getUiSettingsClient with
our useUiSetting$ hook, and with that (and maybe some config setup; I'm
seeing errors at runtime), we should be ready to start migrating other
services.

* Bind a copy of kibana at mock creation

We were previously returning a new copy any time e.g. useKibana was
called, which is not the contract that consumers are expecting. and in
fact caused looping with components employing useEffect etc.

* Remove internal context providers and last usage

We're now using kibana_react fully.

* Fix tests failing due to wrong mocks

Remaining failures are either due to a date format issue, or something
being rendered differently. Those are up next.

Still haven't touched use of chrome.getUiSettingsClient, that's after.

* Fix test failures related to date formatting

* mocks missing UI Setting (DEFAULT_TIMEZONE_BROWSER) which is required
by our formatted_date utilities
* mock timepicker ranges in the one test that uses it (SuperDatePicker)

* Remove unnecessary and/or redundant mocks

Since our TestProvider now mocks new platform, the only tests that
should need to mock uiSettings related stuff (e.g. timezone preferences)
would be the tests that (directly or no) use kibana_react to get it.

* Refactor kibana_react mocks

* adds a mock for the non-observable useUiSetting
* removes the unmockable HOC withKibana

* Replace usage of chrome.getUiSettingsClient with useUiSetting

We're opting for the non-observable behavior here because I believe
that's more analagous.

There are a few remaining usages in non-react code.

Tests are still using the mocks, those'll be removed next.

* Remove ui_settings mocks

Now that we're not using this hook there's no need for the mocks. Tests
are green.

* Remove siem's UI settings hook

We're now using the ones provided by kibana_react.

* Use withKibana HOC on our component classes

React was kind enough to remind me that I can't put hooks in classes.
Whoops.

* Set defaults for some unknown UI settings

The service claims not to know about these settings we're retrieving.
Until I can figure out where they should come from, we're going to
initialize them with what seem to be the defaults at plugin
initialization.

* Remove old hooks

These have now been replaced with kibana_react's equivalents.

* Fix type error on usage of useKibana hook

This is one of the few places where we're using another plugin, which
are not present in the default typings due to their opt-in nature.

* Fix type error on ML call

The indexPattern we get back is actually an array. The endpoint seems to
handle this just fine (at least, it doesn't blow up), but once we
started retrieving a typed value this error surfaced.

* Export a 'bound' version of the useKibana function

Rather than having to type this on each invocation. This requires us to
define which plugins we depend on, which is a good thing.

* Instantiate our mock function

We aren't using these right now I didn't notice, but that wasn't the
right reference.

* Fix test that relies on unmocked service

Our QueryBar component relies very (very, very) indirectly on a storage
service that does not exist in New Platform, nor its corresponding
mocks. To get it passing for now, we're just gonna pretend like it's
there.

* Remove use of ui/chrome in our charts

Replaces with hooks that accomplish the same.

* Remove last use of chrome.getUiSettingsClient

This function is itself a hook, so we should be good here.

* Remove unnecessary non-null assertions

Now that we're using our typed version of the useKibana hook, typescript
knows that these services will be available (once we actually enforce
that in our kibana.json, of course).

* Fix chart tests

These rely on a kibana hook now, so we need to mock it out for these
renders lest we blow up when the context isn't there.

* Replace missing mock

I deleted this in a previous commit, thinking it unneeded.
However, getHostDetailsBreadcrumbs ultimately asks for some
default date parameters for the timerange boundaries.

* Add back tests for our theming hook

* Style: cleanup

* Remove unneeded default UI Settings values

We were previously getting errors due to these values not being known to
the client, but it looks like that was either fixed upstream, or a
temporary issue caused by some improper context setup.

* Simplify kibana_react mocks

Let's leave JSX out of it.

Co-authored-by: Elastic Machine <[email protected]>

* Update references to now-deleted hooks

These hooks were deleted on a recent branch, but new usages were merged
to master in the meantime.

* Fix remaining uses of hooks/chrome that were not merge conflicts

* Use HOC on class component

Co-authored-by: Elastic Machine <[email protected]>

Co-authored-by: Elastic Machine <[email protected]>
jkelastic pushed a commit to jkelastic/kibana that referenced this pull request Jan 8, 2020
* [SIEM] Migrating frontend services to NP (elastic#52783)

* Remove legacy index_patterns import

We'd already brought in the new interface in a previous commit; this was
just used as an unnecessary type assertion.

* Update snapshots following new docLink mocks

* Remove unused manual mocks

These are not picked up by jest; calling
jest.mock('lib/compose/kibana_core') has the same effect whether or not
these files exist.

* WIP: Use kibana core mock everywhere we're doing it manually

The timeline tests are the last place we're explicitly mocking
useKibanaCore; removing the mocks cause tests to hang. I think  hey're
relying on the side effects of importing the mock/ui_settings file, but
I'll figure that out next.

* Replace ui/documentation_links with core NP service

In most instances, this meant using the useContext hook with our NP core
context.

This also updates our mocks to leverage the factory so graciously
provided by platform.

There are a few failing tests, mostly due to links being previously
undefined in tests.

* Use new mocks on timeline test that doesn't hang

The rest of these do, though.

* Remove remaining uses of mockUiSettings in useKibanaCore mocks

These have to be evaluated immediately so that we always return the
same core object. Otherwise we get stuck in a loop between
render/useEffect/setState due to the savedObjects client being different
on each invocation.

* Invoke platform's mock factory at mock time

Previously, we were invoking it any time someone called `useKibanaCore`,
getting a new object back each time. This both caused some bugs (looping
with useEffect) and was not representative of how the actual hook
worked.

This also moves that invokation into the mock function, along with
shaping the mocked module so that we don't have to do it in every call
to jest.mock.

* WIP: migrating to use kibana_react's provider and helpers

We're re-exporting these locally to have more control around mocking
them (until platform implements that).

This breaks everything that was using the old mocks. Will fix.

* WIP: Migrating to use kibana_react

Instead of our homegrown hooks we can use these utilities instead.

Unfortunately kibana_react doesn't yet have mocks, so we had to implement
that ourselves. Luckily, we already had local mocks for the settings
service. This migrates to a the new format. For clarity and consistency,
we also re-export new platform's mocks here and use them to populate our
kibana_react mocks.

We started by migrating the UiSettings service to new platform, and let
that drive the rest. With the mocks in place for kibana_react, removing
the usage of useKibanaCore was a natural step as well.

The next step is removing the usage of chrome.getUiSettingsClient with
our useUiSetting$ hook, and with that (and maybe some config setup; I'm
seeing errors at runtime), we should be ready to start migrating other
services.

* Bind a copy of kibana at mock creation

We were previously returning a new copy any time e.g. useKibana was
called, which is not the contract that consumers are expecting. and in
fact caused looping with components employing useEffect etc.

* Remove internal context providers and last usage

We're now using kibana_react fully.

* Fix tests failing due to wrong mocks

Remaining failures are either due to a date format issue, or something
being rendered differently. Those are up next.

Still haven't touched use of chrome.getUiSettingsClient, that's after.

* Fix test failures related to date formatting

* mocks missing UI Setting (DEFAULT_TIMEZONE_BROWSER) which is required
by our formatted_date utilities
* mock timepicker ranges in the one test that uses it (SuperDatePicker)

* Remove unnecessary and/or redundant mocks

Since our TestProvider now mocks new platform, the only tests that
should need to mock uiSettings related stuff (e.g. timezone preferences)
would be the tests that (directly or no) use kibana_react to get it.

* Refactor kibana_react mocks

* adds a mock for the non-observable useUiSetting
* removes the unmockable HOC withKibana

* Replace usage of chrome.getUiSettingsClient with useUiSetting

We're opting for the non-observable behavior here because I believe
that's more analagous.

There are a few remaining usages in non-react code.

Tests are still using the mocks, those'll be removed next.

* Remove ui_settings mocks

Now that we're not using this hook there's no need for the mocks. Tests
are green.

* Remove siem's UI settings hook

We're now using the ones provided by kibana_react.

* Use withKibana HOC on our component classes

React was kind enough to remind me that I can't put hooks in classes.
Whoops.

* Set defaults for some unknown UI settings

The service claims not to know about these settings we're retrieving.
Until I can figure out where they should come from, we're going to
initialize them with what seem to be the defaults at plugin
initialization.

* Remove old hooks

These have now been replaced with kibana_react's equivalents.

* Fix type error on usage of useKibana hook

This is one of the few places where we're using another plugin, which
are not present in the default typings due to their opt-in nature.

* Fix type error on ML call

The indexPattern we get back is actually an array. The endpoint seems to
handle this just fine (at least, it doesn't blow up), but once we
started retrieving a typed value this error surfaced.

* Export a 'bound' version of the useKibana function

Rather than having to type this on each invocation. This requires us to
define which plugins we depend on, which is a good thing.

* Instantiate our mock function

We aren't using these right now I didn't notice, but that wasn't the
right reference.

* Fix test that relies on unmocked service

Our QueryBar component relies very (very, very) indirectly on a storage
service that does not exist in New Platform, nor its corresponding
mocks. To get it passing for now, we're just gonna pretend like it's
there.

* Remove use of ui/chrome in our charts

Replaces with hooks that accomplish the same.

* Remove last use of chrome.getUiSettingsClient

This function is itself a hook, so we should be good here.

* Remove unnecessary non-null assertions

Now that we're using our typed version of the useKibana hook, typescript
knows that these services will be available (once we actually enforce
that in our kibana.json, of course).

* Fix chart tests

These rely on a kibana hook now, so we need to mock it out for these
renders lest we blow up when the context isn't there.

* Replace missing mock

I deleted this in a previous commit, thinking it unneeded.
However, getHostDetailsBreadcrumbs ultimately asks for some
default date parameters for the timerange boundaries.

* Add back tests for our theming hook

* Style: cleanup

* Remove unneeded default UI Settings values

We were previously getting errors due to these values not being known to
the client, but it looks like that was either fixed upstream, or a
temporary issue caused by some improper context setup.

* Simplify kibana_react mocks

Let's leave JSX out of it.

Co-authored-by: Elastic Machine <[email protected]>

* Update references to now-deleted hooks

These hooks were deleted on a recent branch, but new usages were merged
to master in the meantime.

* Fix remaining uses of hooks/chrome that were not merge conflicts

* Use HOC on class component

Co-authored-by: Elastic Machine <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:New Platform release_note:skip Skip the PR/issue when compiling release notes Team:SIEM v7.6.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants