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

[Infrastructure UI] Implement inventory views CRUD endpoints #154900

Merged
merged 27 commits into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3ec7402
feat(infra): wip on inventory views
Apr 11, 2023
10e34e8
refactor(infra): move saved objects into server
Apr 11, 2023
a7c9330
feat(infra): add inventory view to common types with versioning
Apr 11, 2023
c3d9c8e
feat(infra): wip endpoints
Apr 12, 2023
bab4c46
feat(infra): implement inventory view endpoints
Apr 13, 2023
6df39b1
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Apr 13, 2023
a6d9262
fix(infra): update saved object runtime type
Apr 13, 2023
70a6f5f
feat(infra): add static view
Apr 13, 2023
e71d868
docs(infra): add doc about endpoints
Apr 13, 2023
15b88a1
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 17, 2023
d21947a
refactor(infra): restore legacy saved view files until client is refa…
Apr 17, 2023
85881d3
tests(infra): add inventoryViews test
Apr 17, 2023
418b3b1
feat(infra): init metrics explorer view common
Apr 17, 2023
bfa86b9
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 17, 2023
6a18272
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 17, 2023
59e6e33
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 18, 2023
1af7672
feat(infra): update type imports
Apr 18, 2023
426f924
fix(infra): typo
Apr 18, 2023
8ba830c
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 19, 2023
2e3e551
refactor(infra): sort inventory views with default on top
Apr 19, 2023
547963f
refactor(infra): switch back to old default id
Apr 19, 2023
5120167
test(infra): update broken test
Apr 19, 2023
8efe997
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 20, 2023
72086f1
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Apr 20, 2023
ead0118
refactor(infra): request changes
Apr 24, 2023
0b71493
Merge branch 'main' into 152617-saved-views-http-endpoints
tonyghiani Apr 24, 2023
88466a4
fix(infra): update test types
Apr 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/kbn-io-ts-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

export type { IndexPatternType } from './src/index_pattern_rt';
export type { NonEmptyStringBrand } from './src/non_empty_string_rt';
export type { NonEmptyString, NonEmptyStringBrand } from './src/non_empty_string_rt';

export { deepExactRt } from './src/deep_exact_rt';
export { indexPatternRt } from './src/index_pattern_rt';
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/infra/common/http_api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ export * from './log_alerts';
export * from './snapshot_api';
export * from './host_details';
export * from './infra';

/**
* Exporting versioned APIs types
*/
export * from './latest';
export * as inventoryViewsV1 from './inventory_views/v1';
66 changes: 66 additions & 0 deletions x-pack/plugins/infra/common/http_api/inventory_views/v1/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 { nonEmptyStringRt } from '@kbn/io-ts-utils';
import * as rt from 'io-ts';
import { either } from 'fp-ts/Either';

export const INVENTORY_VIEW_URL = '/api/infra/inventory_views';
export const INVENTORY_VIEW_URL_ENTITY = `${INVENTORY_VIEW_URL}/{inventoryViewId}`;
export const getInventoryViewUrl = (inventoryViewId?: string) =>
[INVENTORY_VIEW_URL, inventoryViewId].filter(Boolean).join('/');

const inventoryViewIdRT = new rt.Type<string, string, unknown>(
'InventoryViewId',
rt.string.is,
(u, c) =>
either.chain(rt.string.validate(u, c), (id) => {
return id === '0'
? rt.failure(u, c, `The inventory view with id ${id} is not configurable.`)
: rt.success(id);
}),
String
);

export const inventoryViewRequestParamsRT = rt.type({
inventoryViewId: inventoryViewIdRT,
});

export type InventoryViewRequestParams = rt.TypeOf<typeof inventoryViewRequestParamsRT>;

export const inventoryViewRequestQueryRT = rt.partial({
sourceId: rt.string,
});

export type InventoryViewRequestQuery = rt.TypeOf<typeof inventoryViewRequestQueryRT>;

const inventoryViewAttributesResponseRT = rt.intersection([
Copy link
Contributor Author

@tonyghiani tonyghiani Apr 19, 2023

Choose a reason for hiding this comment

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

note: for the attributes of this saved object, the configuration has always been dynamic and not strictly typed. As they can vary depending on the user usage on the page, I left it open to all the attributes as it was before, marking only those that I'm sure will be present in the response.

This applies to any other attributes definition you'll find for this attribute's saved object.

rt.strict({
name: nonEmptyStringRt,
isDefault: rt.boolean,
isStatic: rt.boolean,
Comment on lines +43 to +44
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note:

  • isDefault represent whether a saved view is the default one by user preference.
  • isStatic is used to distinguish the static saved view that will always be present and served, now hardcoded in the server and not configurable.

Copy link
Member

Choose a reason for hiding this comment

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

Can those values change using the API? For example, using the update endpoint to set another default view?

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 those values are derived as:

  • isDefault: match with the inventoryDefaultView configuration saved in the source configuration
  • isStatic is a statically set value to false

They could insert those values triggering a manual request to the endpoint, but I guess is better to handle the case, I'll change that!

}),
rt.UnknownRecord,
]);

const inventoryViewResponseRT = rt.exact(
rt.intersection([
rt.type({
id: rt.string,
attributes: inventoryViewAttributesResponseRT,
}),
rt.partial({
updatedAt: rt.number,
version: rt.string,
}),
])
);

export const inventoryViewResponsePayloadRT = rt.type({
data: inventoryViewResponseRT,
});

export type GetInventoryViewResponsePayload = rt.TypeOf<typeof inventoryViewResponsePayloadRT>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 { nonEmptyStringRt } from '@kbn/io-ts-utils';
import * as rt from 'io-ts';

export const createInventoryViewAttributesRequestPayloadRT = rt.intersection([
rt.type({
name: nonEmptyStringRt,
}),
rt.UnknownRecord,
rt.exact(rt.partial({ isDefault: rt.undefined, isStatic: rt.undefined })),
]);

export type CreateInventoryViewAttributesRequestPayload = rt.TypeOf<
typeof createInventoryViewAttributesRequestPayloadRT
>;

export const createInventoryViewRequestPayloadRT = rt.type({
attributes: createInventoryViewAttributesRequestPayloadRT,
});

export type CreateInventoryViewRequestPayload = rt.TypeOf<
typeof createInventoryViewRequestPayloadRT
>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 { nonEmptyStringRt } from '@kbn/io-ts-utils';
import * as rt from 'io-ts';

export const findInventoryViewAttributesResponseRT = rt.strict({
name: nonEmptyStringRt,
isDefault: rt.boolean,
isStatic: rt.boolean,
});

const findInventoryViewResponseRT = rt.exact(
rt.intersection([
rt.type({
id: rt.string,
attributes: findInventoryViewAttributesResponseRT,
}),
rt.partial({
updatedAt: rt.number,
version: rt.string,
}),
])
);

export const findInventoryViewResponsePayloadRT = rt.type({
data: rt.array(findInventoryViewResponseRT),
});

export type FindInventoryViewResponsePayload = rt.TypeOf<typeof findInventoryViewResponsePayloadRT>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 * as rt from 'io-ts';

export const getInventoryViewRequestParamsRT = rt.type({
inventoryViewId: rt.string,
});

export type GetInventoryViewRequestParams = rt.TypeOf<typeof getInventoryViewRequestParamsRT>;
12 changes: 12 additions & 0 deletions x-pack/plugins/infra/common/http_api/inventory_views/v1/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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.
*/

export * from './common';
export * from './get_inventory_view';
export * from './find_inventory_view';
export * from './create_inventory_view';
export * from './update_inventory_view';
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 { nonEmptyStringRt } from '@kbn/io-ts-utils';
import * as rt from 'io-ts';

export const updateInventoryViewAttributesRequestPayloadRT = rt.intersection([
rt.type({
name: nonEmptyStringRt,
}),
rt.UnknownRecord,
rt.exact(rt.partial({ isDefault: rt.undefined, isStatic: rt.undefined })),
]);

export type UpdateInventoryViewAttributesRequestPayload = rt.TypeOf<
typeof updateInventoryViewAttributesRequestPayloadRT
>;

export const updateInventoryViewRequestPayloadRT = rt.type({
attributes: updateInventoryViewAttributesRequestPayloadRT,
});

export type UpdateInventoryViewRequestPayload = rt.TypeOf<
typeof updateInventoryViewRequestPayloadRT
>;
8 changes: 8 additions & 0 deletions x-pack/plugins/infra/common/http_api/latest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export * from './inventory_views/v1';
52 changes: 52 additions & 0 deletions x-pack/plugins/infra/common/inventory_views/defaults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { NonEmptyString } from '@kbn/io-ts-utils';
import type { InventoryViewAttributes } from './types';

export const staticInventoryViewId = '0';

export const staticInventoryViewAttributes: InventoryViewAttributes = {
name: i18n.translate('xpack.infra.savedView.defaultViewNameHosts', {
defaultMessage: 'Default view',
}) as NonEmptyString,
isDefault: false,
isStatic: true,
metric: {
type: 'cpu',
},
groupBy: [],
nodeType: 'host',
view: 'map',
customOptions: [],
boundsOverride: {
max: 1,
min: 0,
},
autoBounds: true,
accountId: '',
region: '',
customMetrics: [],
legend: {
palette: 'cool',
steps: 10,
reverseColors: false,
},
source: 'default',
sort: {
by: 'name',
direction: 'desc',
},
timelineOpen: false,
filterQuery: {
kind: 'kuery',
expression: '',
},
time: Date.now(),
autoReload: false,
};
9 changes: 9 additions & 0 deletions x-pack/plugins/infra/common/inventory_views/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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.
*/

export * from './defaults';
export * from './types';
24 changes: 24 additions & 0 deletions x-pack/plugins/infra/common/inventory_views/inventory_view.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 { staticInventoryViewAttributes } from './defaults';
import type { InventoryView, InventoryViewAttributes } from './types';

export const createInventoryViewMock = (
id: string,
attributes: InventoryViewAttributes,
updatedAt?: number,
version?: string
): InventoryView => ({
id,
attributes: {
...staticInventoryViewAttributes,
...attributes,
},
updatedAt,
version,
});
35 changes: 35 additions & 0 deletions x-pack/plugins/infra/common/inventory_views/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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 { nonEmptyStringRt } from '@kbn/io-ts-utils';
import * as rt from 'io-ts';

export const inventoryViewAttributesRT = rt.intersection([
rt.strict({
name: nonEmptyStringRt,
isDefault: rt.boolean,
isStatic: rt.boolean,
}),
rt.UnknownRecord,
]);

export type InventoryViewAttributes = rt.TypeOf<typeof inventoryViewAttributesRT>;

export const inventoryViewRT = rt.exact(
rt.intersection([
rt.type({
id: rt.string,
attributes: inventoryViewAttributesRT,
}),
rt.partial({
updatedAt: rt.number,
version: rt.string,
}),
])
);

export type InventoryView = rt.TypeOf<typeof inventoryViewRT>;
51 changes: 51 additions & 0 deletions x-pack/plugins/infra/common/metrics_explorer_views/defaults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { NonEmptyString } from '@kbn/io-ts-utils';
import type { MetricsExplorerViewAttributes } from './types';

export const staticMetricsExplorerViewId = 'static';

export const staticMetricsExplorerViewAttributes: MetricsExplorerViewAttributes = {
name: i18n.translate('xpack.infra.savedView.defaultViewNameHosts', {
defaultMessage: 'Default view',
}) as NonEmptyString,
isDefault: false,
isStatic: true,
options: {
aggregation: 'avg',
metrics: [
{
aggregation: 'avg',
field: 'system.cpu.total.norm.pct',
color: 'color0',
},
{
aggregation: 'avg',
field: 'kubernetes.pod.cpu.usage.node.pct',
color: 'color1',
},
{
aggregation: 'avg',
field: 'docker.cpu.total.pct',
color: 'color2',
},
],
source: 'default',
},
chartOptions: {
type: 'line',
yAxisMode: 'fromZero',
stack: false,
},
currentTimerange: {
from: 'now-1h',
to: 'now',
interval: '>=10s',
},
};
Loading