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

Task/hostlist pagination #63722

Merged
merged 21 commits into from
Apr 24, 2020
Merged

Conversation

parkiino
Copy link
Contributor

@parkiino parkiino commented Apr 16, 2020

Summary

**Parent Ticket: https://github.com/elastic/endpoint-app-team/issues/331 **

This PR drives host pagination through the URL.

Additionally addresses some wrapping/truncation problems with the hostname in host details as well as truncates all longer values in the host list so that the list is max one line.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@parkiino parkiino marked this pull request as ready for review April 21, 2020 19:32
@parkiino parkiino requested a review from a team as a code owner April 21, 2020 19:33
@parkiino parkiino added Feature:Endpoint Elastic Endpoint feature release_note:skip Skip the PR/issue when compiling release notes Team:Endpoint Management v7.8.0 v8.0.0 labels Apr 21, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-app-team (Feature:Endpoint)

@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-management (Team:Endpoint Management)

`);
});
});
describe('when an invalid page size is passed', () => {
Copy link
Contributor

@paul-tavares paul-tavares Apr 22, 2020

Choose a reason for hiding this comment

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

Are there any other variations you should be testing? Example: what if multiple page_size params are in the URL? what if page_size is -1? or a string (jsdkfjkds)?

Also - might be worth testing that the parameters get correcly passed down to the middleware/API.

Choose a reason for hiding this comment

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

Yes, I agree with @paul-tavares - @parkiino we should test the following invalid values as well:

  • -1
  • invalid UUID
  • valid UUID + special characters
  • valid UUID + JS embed
  • valid UUID + unicode
  • empty string

If it's too much of a lift, I can also test these examples manually and create another ticket to automate these tests in the future. I will also manually test when page_index is more than what we expect to make sure it results in the same bug I found in the policy list URL pagination

@@ -56,7 +56,7 @@ describe('host list middleware', () => {
await sleep();
Copy link
Contributor

Choose a reason for hiding this comment

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

we should remove the sleeps and instead use the new utility that allows you to wait for a given action to be dispatched - in this case, its probably the serverReturnedHostListData action.

}
if (action.type === 'userChangedUrl' && hasSelectedHost(state) !== false) {
// If user navigated directly to a host details page, load the host list
if (listData(state).length === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If a list API call was done, but there were no hosts in the list, then this if() would alway match. Its unlikely to happen now, but when we introduce the KQL bar, then I can see this being an issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that's true. i'm not sure what to do at that point once the kql bar is introduced. maybe it will be possible to additionally check if filters are active at that point? otherwise, for now i think this makes the most sense for the details page

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, this would be where perhaps we should track wether the list has been loaded (once) at least. Not a big deal. I guess we can re-evaluate when we introduce filtering

if (listData(state).length === 0) {
const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(state);
try {
const response = await coreStart.http.post('/api/endpoint/metadata', {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was going to suggest that we add typing to response by doing:

Suggested change
const response = await coreStart.http.post('/api/endpoint/metadata', {
const response = await coreStart.http.post<HostInfo>('/api/endpoint/metadata', {

But I just realized that you then get an error because HostInfo type has been made Imutable (cc/ @oatkiller - maybe making everthing Immutable is the best approach? :) )

Copy link
Contributor

Choose a reason for hiding this comment

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

not sure i'm following. HostInfo is immutable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@paul-tavares i think i can type the response, but wouldn't it be HostResultList?

Copy link
Contributor

Choose a reason for hiding this comment

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

My mistake - @parkiino you are correct - you should use HostResultList type here :)

};
}
}
// otherwise we are not on a host list or details page
return {
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably should reset the entire state as in:

return initialState();

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 know there's something going on to move the location out of all the individual reducers but that hasn't merged yet right? initially i did it that way so that the location would still be updated in the host reducer

history.push(
urlFromQueryParams({
...queryParams,
page_index: JSON.stringify(index),
Copy link
Contributor

Choose a reason for hiding this comment

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

(optional) You don't need stringify here and below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because the type is actually set up as string, typescript complains if i don't have stringify it here. maybe i should just turn that into a number and all will be solved?!

@paul-tavares
Copy link
Contributor

I checked out the pull request and ran it locally. Here is some more feedback:

  • Closing the Details Flyout panel seems to trigger a new API request to populate the list
  • Should this message above the table Showing: 100 really be Total: 100? (cc/ @bfishel ) Since the table is really not showing 100.
  • How should we display errors on Lists? In this PR, the EUI Table error property is being used, which shows the error in the table (screen capture below (I forced the error in code, so disregard the actual message)), but in Policy List, we're using a Toaster notification. We should sync up what the expected behaviour should be - @bfishel can you help here? 😃 (ps. I like the approach that @parkiino took in screen capture below):
    image

@@ -56,7 +56,7 @@ describe('host list middleware', () => {
await sleep();
expect(fakeHttpServices.post).toHaveBeenCalledWith('/api/endpoint/metadata', {
body: JSON.stringify({
paging_properties: [{ page_index: 0 }, { page_size: 10 }],
paging_properties: [{ page_index: '0' }, { page_size: '10' }],
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 page_index and page_size are strings because they are coming from the url now

Copy link
Contributor

Choose a reason for hiding this comment

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

This does not seem valid. The Server Schema for the metadata POST request indicates these should be numbers.
See

page_size: schema.number({ defaultValue: 10, min: 1, max: 10000 }),

if you are sending strings to the server now (in the browser) and that is succeeding, then perhaps the platform translates it back to a number 🤷‍♂️


// if on the host list page for the first time, return new location and load list
if (isCurrentlyOnListPage) {
if (!wasPreviouslyOnListPage) {
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 currently refresh the list if the user closes a host details flyout

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 the logic that decides to set loading to true here should be used to decide when to actually make the request.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as opposed to in the middleware? not really sure i understand what you mean

paging_properties: [{ page_index: pageIndex }, { page_size: pageSize }],
}),
});
response.request_page_index = Number(pageIndex);
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the purpose of this?

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 api doesn't return the page index that the ui would use so we manually set it in the ui

Copy link
Contributor

Choose a reason for hiding this comment

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

Consider typing response with a type that's shared with the server. If the server should be returning this value, why don't you just change the code there instead of here?

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 server returns what would originally be returned from an elastic search query, which is the page index within elastic i think? or something like that. so it seemed to make more sense to be consistent with that

@@ -88,23 +88,40 @@ export type SubstateMiddlewareFactory = <Substate>(
middleware: ImmutableMiddleware<Substate, AppAction>
) => Middleware<{}, GlobalState, Dispatch<AppAction | Immutable<AppAction>>>;

export interface HostListState {
export interface HostState {
/** list of host **/
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@oatkiller oatkiller left a comment

Choose a reason for hiding this comment

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

few q's

Copy link

@aisantos aisantos left a comment

Choose a reason for hiding this comment

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

@parkiino - can you review these test cases and update the AC for host list pagination? I can document them in TestRail for us. I checked off the ones already in your PR. I'll execute the others manually until we can automate later:

  • host list url params uses page_index with an invalid value
  • host list url params has a page_index with a value that is more than total pagination
  • host list displays correct page when using url params directly
  • host list url params accepts only positive numbers for page_index and page_size
  • host list url params accepts only a value of 10, 20 or 50 for page_size (what are our defaults?)
  • host list url params ignores unknown search params
  • host list url params uses only first search param value if multiple values are present
  • host list url params uses defaults for any missing search params

Object {
"page_index": "0",
"page_size": "20",
}

Choose a reason for hiding this comment

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

@parkiino - are these values the defaults we are using? It would be good to test the defaults for this test case and have a separate test case for invalid values that revert to defaults.

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 defaults are going to be page_index: 0, and page_size: 10

`);
});
});
describe('when an invalid page size is passed', () => {

Choose a reason for hiding this comment

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

Yes, I agree with @paul-tavares - @parkiino we should test the following invalid values as well:

  • -1
  • invalid UUID
  • valid UUID + special characters
  • valid UUID + JS embed
  • valid UUID + unicode
  • empty string

If it's too much of a lift, I can also test these examples manually and create another ticket to automate these tests in the future. I will also manually test when page_index is more than what we expect to make sure it results in the same bug I found in the policy list URL pagination

@parkiino
Copy link
Contributor Author

parkiino commented Apr 22, 2020

@aisantos

  • host list url params uses page_index with an invalid value
    host list url params has a page_index with a value that is more than total pagination
  • host list displays correct page when using url params directly
  • host list url params accepts only positive numbers for page_index and page_size
  • host list url params accepts only a value of 10, 20 or 50 for page_size (10 is the default)
  • host list url params ignores unknown search params
  • host list url params uses only first search param value if multiple values are present
  • host list url params uses defaults for any missing search params

@@ -56,7 +56,7 @@ describe('host list middleware', () => {
await sleep();
expect(fakeHttpServices.post).toHaveBeenCalledWith('/api/endpoint/metadata', {
body: JSON.stringify({
paging_properties: [{ page_index: 0 }, { page_size: 10 }],
paging_properties: [{ page_index: '0' }, { page_size: '10' }],
Copy link
Contributor

Choose a reason for hiding this comment

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

This does not seem valid. The Server Schema for the metadata POST request indicates these should be numbers.
See

page_size: schema.number({ defaultValue: 10, min: 1, max: 10000 }),

if you are sending strings to the server now (in the browser) and that is succeeding, then perhaps the platform translates it back to a number 🤷‍♂️

}
if (action.type === 'userChangedUrl' && hasSelectedHost(state) !== false) {
// If user navigated directly to a host details page, load the host list
if (listData(state).length === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, this would be where perhaps we should track wether the list has been loaded (once) at least. Not a big deal. I guess we can re-evaluate when we introduce filtering

if (listData(state).length === 0) {
const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(state);
try {
const response = await coreStart.http.post('/api/endpoint/metadata', {
Copy link
Contributor

Choose a reason for hiding this comment

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

My mistake - @parkiino you are correct - you should use HostResultList type here :)

Copy link

@aisantos aisantos left a comment

Choose a reason for hiding this comment

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

Looks good @parkiino

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

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

Copy link
Contributor

@kevinlog kevinlog left a comment

Choose a reason for hiding this comment

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

Talked with @oatkiller , he's OK for us to move forward with this, we can address additional issues in another PR

@kevinlog kevinlog dismissed oatkiller’s stale review April 24, 2020 13:52

Spoke with Rob, he's OK for us to move forward, we can make sure his questions are answered sufficiently in another PR

@parkiino parkiino merged commit fb70f01 into elastic:master Apr 24, 2020
@parkiino parkiino deleted the task/hostlist-pagination branch April 24, 2020 14:01
parkiino added a commit that referenced this pull request Apr 24, 2020
* hostlist pagination for endpoint security
jloleysens added a commit to jloleysens/kibana that referenced this pull request Apr 27, 2020
…bana into ingest-node-pipeline/open-flyout-create-edit

* 'feature/ingest-node-pipelines' of github.com:elastic/kibana: (116 commits)
  [Ingest Node Pipelines] More lenient treatment of on-failure value (elastic#64411)
  Report Deletion via UI- functional test (elastic#64031)
  Bump handlebars dependency from 4.5.3 to 4.7.6 (elastic#64402)
  [Uptime] Update TLS settings (elastic#64111)
  [alerting] removes usage of any throughout Alerting Services code (elastic#64161)
  [CANVAS] Moves notify to a canvas service (elastic#63268)
  [Canvas] Misc NP Stuff (elastic#63703)
  update apm index pattern (elastic#64232)
  Task/hostlist pagination (elastic#63722)
  [NP] Vega migration (elastic#63849)
  Move ensureDefaultIndexPattern into data plugin (elastic#63100)
  [Fleet] Fix agent status count to not include unenrolled agents (elastic#64106)
  Migrate graph_workspace saved object registration to Kibana platform (elastic#64157)
  Index pattern management UI -> TypeScript and New Platform Ready (edit_index_pattern) (elastic#64184)
  [ML] EuiDataGrid ml/transform components. (elastic#63447)
  [ML] Moving to kibana capabilities (elastic#64057)
  Move input_control_vis into NP (elastic#63333)
  remove reference to local application service in graph (elastic#64288)
  KQL removes leading zero and breaks query (elastic#62748)
  [FieldFormats] Cleanup: rename IFieldFormatType -> FieldFormatInstanceType (elastic#64193)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Endpoint Elastic Endpoint feature release_note:skip Skip the PR/issue when compiling release notes v7.8.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants