-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Add inventory locator #183418
Add inventory locator #183418
Changes from 5 commits
be071f0
d8a6ef9
647f7ed
397ee00
91d6ecf
26b7c86
4ab66b1
40cd838
21a1cf0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,92 @@ | ||||||||||||||||||||||||
/* | ||||||||||||||||||||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||||||||||||||||||||||||
* or more contributor license agreements. Licensed under the Elastic License | ||||||||||||||||||||||||
* 2.0; you may not use this file except in compliance with the Elastic License | ||||||||||||||||||||||||
* 2.0. | ||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||
import type { SerializableRecord } from '@kbn/utility-types'; | ||||||||||||||||||||||||
import rison from '@kbn/rison'; | ||||||||||||||||||||||||
import { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/common'; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
export type InventoryLocator = LocatorPublic<InventoryLocatorParams>; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
export interface InventoryLocatorParams extends SerializableRecord { | ||||||||||||||||||||||||
inventoryViewId?: string; | ||||||||||||||||||||||||
waffleFilter?: { | ||||||||||||||||||||||||
expression: string; | ||||||||||||||||||||||||
kind: string; | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
waffleTime?: { | ||||||||||||||||||||||||
currentTime: number; | ||||||||||||||||||||||||
isAutoReloading: boolean; | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
waffleOptions?: { | ||||||||||||||||||||||||
accountId: string; | ||||||||||||||||||||||||
autoBounds: boolean; | ||||||||||||||||||||||||
boundsOverride: { | ||||||||||||||||||||||||
max: number; | ||||||||||||||||||||||||
min: number; | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
customMetrics?: string; // encoded value | ||||||||||||||||||||||||
customOptions?: string; // encoded value | ||||||||||||||||||||||||
groupBy?: { field: string }; | ||||||||||||||||||||||||
legend?: { | ||||||||||||||||||||||||
palette: string; | ||||||||||||||||||||||||
reverseColors: boolean; | ||||||||||||||||||||||||
steps: number; | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
metric: string; // encoded value | ||||||||||||||||||||||||
nodeType: string; | ||||||||||||||||||||||||
region?: string; | ||||||||||||||||||||||||
sort: { | ||||||||||||||||||||||||
by: string; | ||||||||||||||||||||||||
direction: 'desc' | 'async'; | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
timelineOpen: boolean; | ||||||||||||||||||||||||
view: 'map' | 'table'; | ||||||||||||||||||||||||
state?: SerializableRecord; | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
export const INVENTORY_LOCATOR_ID = 'INVENTORY_LOCATOR'; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
export class InventoryLocatorDefinition implements LocatorDefinition<InventoryLocatorParams> { | ||||||||||||||||||||||||
public readonly id = INVENTORY_LOCATOR_ID; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
public readonly getLocation = async (params: InventoryLocatorParams) => { | ||||||||||||||||||||||||
const paramsWithDefaults = { | ||||||||||||||||||||||||
waffleFilter: rison.encodeUnknown(params.waffleFilter ?? { kind: 'kuery', expression: '' }), | ||||||||||||||||||||||||
waffleTime: rison.encodeUnknown( | ||||||||||||||||||||||||
params.waffleTime ?? { | ||||||||||||||||||||||||
currentTime: new Date().getTime(), | ||||||||||||||||||||||||
isAutoReloading: false, | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
), | ||||||||||||||||||||||||
waffleOptions: rison.encodeUnknown( | ||||||||||||||||||||||||
params.waffleOptions ?? { | ||||||||||||||||||||||||
accountId: '', | ||||||||||||||||||||||||
autoBounds: true, | ||||||||||||||||||||||||
boundsOverride: { max: 1, min: 0 }, | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
), | ||||||||||||||||||||||||
customMetrics: params.customMetrics || rison.encodeUnknown(''), | ||||||||||||||||||||||||
customOptions: params.customOptions || rison.encodeUnknown(''), | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is needed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It adds |
||||||||||||||||||||||||
groupBy: rison.encodeUnknown(params.groupBy ?? {}), | ||||||||||||||||||||||||
legend: rison.encodeUnknown( | ||||||||||||||||||||||||
params.legend ?? { palette: 'cool', reverseColors: false, steps: 10 } | ||||||||||||||||||||||||
), | ||||||||||||||||||||||||
metric: params.metric, | ||||||||||||||||||||||||
nodeType: rison.encodeUnknown(params.nodeType), | ||||||||||||||||||||||||
region: rison.encodeUnknown(params.region ?? ''), | ||||||||||||||||||||||||
sort: rison.encodeUnknown(params.sort ?? { by: 'name', direction: 'desc' }), | ||||||||||||||||||||||||
timelineOpen: rison.encodeUnknown(params.timelineOpen ?? false), | ||||||||||||||||||||||||
view: rison.encodeUnknown(params.view ?? 'map'), | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return { | ||||||||||||||||||||||||
app: 'metrics', | ||||||||||||||||||||||||
path: `/inventory?waffleFilter=${paramsWithDefaults.waffleFilter}&waffleTime=${paramsWithDefaults.waffleTime}&waffleOptions=${paramsWithDefaults.waffleOptions}&customMetrics=${paramsWithDefaults.customMetrics}&customOptions=${paramsWithDefaults.customOptions}&groupBy=${paramsWithDefaults.groupBy}&legend=${paramsWithDefaults.legend}&metric=${paramsWithDefaults.metric}&nodeType=${paramsWithDefaults.nodeType}®ion=${paramsWithDefaults.region}&sort=${paramsWithDefaults.sort}&timelineOpen=${paramsWithDefaults.timelineOpen}&view=${paramsWithDefaults.view}`, | ||||||||||||||||||||||||
state: params.state ? params.state : {}, | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would this work?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea, thanks 👍 I started with just 3 params then decided to support more in case we need them 😅 |
||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -9,6 +9,7 @@ import rison from '@kbn/rison'; | |||||||||||||||||||||||||||||||||||
import { AssetDetailsLocatorDefinition } from './asset_details_locator'; | ||||||||||||||||||||||||||||||||||||
import { AssetDetailsFlyoutLocatorDefinition } from './asset_details_flyout_locator'; | ||||||||||||||||||||||||||||||||||||
import { HostsLocatorDefinition } from './hosts_locator'; | ||||||||||||||||||||||||||||||||||||
import { InventoryLocatorDefinition } from './inventory_locator'; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
const setupAssetDetailsLocator = async () => { | ||||||||||||||||||||||||||||||||||||
const assetDetailsLocator = new AssetDetailsLocatorDefinition(); | ||||||||||||||||||||||||||||||||||||
|
@@ -28,6 +29,14 @@ const setupHostsLocator = async () => { | |||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
const setupInventoryLocator = async () => { | ||||||||||||||||||||||||||||||||||||
const inventoryLocator = new InventoryLocatorDefinition(); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||
inventoryLocator, | ||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
describe('Infra Locators', () => { | ||||||||||||||||||||||||||||||||||||
describe('Asset Details Locator', () => { | ||||||||||||||||||||||||||||||||||||
const params = { | ||||||||||||||||||||||||||||||||||||
|
@@ -162,4 +171,67 @@ describe('Infra Locators', () => { | |||||||||||||||||||||||||||||||||||
expect(Object.keys(state)).toHaveLength(0); | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
describe('Inventory Locator', () => { | ||||||||||||||||||||||||||||||||||||
const params = { | ||||||||||||||||||||||||||||||||||||
waffleFilter: { kind: 'kuery', expression: '' }, | ||||||||||||||||||||||||||||||||||||
waffleTime: { | ||||||||||||||||||||||||||||||||||||
currentTime: 1715688477985, | ||||||||||||||||||||||||||||||||||||
isAutoReloading: false, | ||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||
waffleOptions: { | ||||||||||||||||||||||||||||||||||||
accountId: '', | ||||||||||||||||||||||||||||||||||||
autoBounds: true, | ||||||||||||||||||||||||||||||||||||
boundsOverride: { max: 1, min: 0 }, | ||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||
customMetrics: '', | ||||||||||||||||||||||||||||||||||||
customOptions: '', | ||||||||||||||||||||||||||||||||||||
groupBy: { field: 'cloud.provider' }, | ||||||||||||||||||||||||||||||||||||
legend: { palette: 'cool', reverseColors: false, steps: 10 }, | ||||||||||||||||||||||||||||||||||||
metric: '(type:cpu)', | ||||||||||||||||||||||||||||||||||||
nodeType: 'host', | ||||||||||||||||||||||||||||||||||||
region: '', | ||||||||||||||||||||||||||||||||||||
sort: { by: 'name', direction: 'desc' as const }, | ||||||||||||||||||||||||||||||||||||
timelineOpen: false, | ||||||||||||||||||||||||||||||||||||
view: 'map' as const, | ||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
const waffleFilter = rison.encodeUnknown(params.waffleFilter); | ||||||||||||||||||||||||||||||||||||
const waffleTime = rison.encodeUnknown(params.waffleTime); | ||||||||||||||||||||||||||||||||||||
const waffleOptions = rison.encodeUnknown(params.waffleOptions); | ||||||||||||||||||||||||||||||||||||
const customMetrics = rison.encodeUnknown(params.customMetrics); | ||||||||||||||||||||||||||||||||||||
const customOptions = rison.encodeUnknown(params.customOptions); | ||||||||||||||||||||||||||||||||||||
const groupBy = rison.encodeUnknown(params.groupBy); | ||||||||||||||||||||||||||||||||||||
const legend = rison.encodeUnknown(params.legend); | ||||||||||||||||||||||||||||||||||||
const metric = params.metric; | ||||||||||||||||||||||||||||||||||||
const nodeType = rison.encodeUnknown(params.nodeType); | ||||||||||||||||||||||||||||||||||||
const region = rison.encodeUnknown(params.region); | ||||||||||||||||||||||||||||||||||||
const sort = rison.encodeUnknown(params.sort); | ||||||||||||||||||||||||||||||||||||
const timelineOpen = rison.encodeUnknown(params.timelineOpen); | ||||||||||||||||||||||||||||||||||||
const view = rison.encodeUnknown(params.view); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it makes sense, fixed! Sorry about those I was testing with different things and with/without encoding and forgot to remove and fix that. |
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
it('should create a link to Inventory with no state', async () => { | ||||||||||||||||||||||||||||||||||||
const { inventoryLocator } = await setupInventoryLocator(); | ||||||||||||||||||||||||||||||||||||
const { app, path, state } = await inventoryLocator.getLocation(params); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
expect(app).toBe('metrics'); | ||||||||||||||||||||||||||||||||||||
expect(path).toBe( | ||||||||||||||||||||||||||||||||||||
`/inventory?waffleFilter=${waffleFilter}&waffleTime=${waffleTime}&waffleOptions=${waffleOptions}&customMetrics=${customMetrics}&customOptions=${customOptions}&groupBy=${groupBy}&legend=${legend}&metric=${metric}&nodeType=${nodeType}®ion=${region}&sort=${sort}&timelineOpen=${timelineOpen}&view=${view}` | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should also work here
Suggested change
|
||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||
expect(state).toBeDefined(); | ||||||||||||||||||||||||||||||||||||
expect(Object.keys(state)).toHaveLength(0); | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
it('should return correct structured url', async () => { | ||||||||||||||||||||||||||||||||||||
const { inventoryLocator } = await setupInventoryLocator(); | ||||||||||||||||||||||||||||||||||||
const { app, path, state } = await inventoryLocator.getLocation(params); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
expect(app).toBe('metrics'); | ||||||||||||||||||||||||||||||||||||
expect(path).toBe( | ||||||||||||||||||||||||||||||||||||
`/inventory?waffleFilter=${waffleFilter}&waffleTime=${waffleTime}&waffleOptions=${waffleOptions}&customMetrics=${customMetrics}&customOptions=${customOptions}&groupBy=${groupBy}&legend=${legend}&metric=${metric}&nodeType=${nodeType}®ion=${region}&sort=${sort}&timelineOpen=${timelineOpen}&view=${view}` | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||
expect(state).toBeDefined(); | ||||||||||||||||||||||||||||||||||||
expect(Object.keys(state)).toHaveLength(0); | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😮