Skip to content

Commit

Permalink
[Infrastructure UI] Create InventoryViewsService and InventoryViewsCl…
Browse files Browse the repository at this point in the history
…ient (#155126)

## 📓 Summary

Depends on #154900
Closes #155110 

This PR implements the `InventoryViewsService` and
`InventoryViewsClient`, injecting an instance of the client in the
KibanaContextForPlugin and exposing so a set of utilities to
retrieve/update inventory views:
- `findInventoryViews`
- `getInventoryView`
- `createInventoryView`
- `updateInventoryView`
- `deleteInventoryView`

## 👣 Next steps
- Implement #154725 to consume the service

---------

Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 26, 2023
1 parent 636674c commit 1351760
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 1 deletion.
32 changes: 32 additions & 0 deletions x-pack/plugins/infra/common/inventory_views/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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.
*/

/* eslint-disable max-classes-per-file */

export class FetchInventoryViewError extends Error {
constructor(message: string, public cause?: Error) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
this.name = 'FetchInventoryViewError';
}
}

export class UpsertInventoryViewError extends Error {
constructor(message: string, public cause?: Error) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
this.name = 'UpsertInventoryViewError';
}
}

export class DeleteInventoryViewError extends Error {
constructor(message: string, public cause?: Error) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
this.name = 'DeleteInventoryViewError';
}
}
2 changes: 1 addition & 1 deletion x-pack/plugins/infra/common/inventory_views/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export * from './defaults';
export * from './errors';
export * from './types';
2 changes: 2 additions & 0 deletions x-pack/plugins/infra/public/mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
*/

import React from 'react';
import { createInventoryViewsServiceStartMock } from './services/inventory_views/inventory_views_service.mock';
import { createLogViewsServiceStartMock } from './services/log_views/log_views_service.mock';
import { createTelemetryServiceMock } from './services/telemetry/telemetry_service.mock';
import { InfraClientStartExports } from './types';

export const createInfraPluginStartMock = () => ({
inventoryViews: createInventoryViewsServiceStartMock(),
logViews: createLogViewsServiceStartMock(),
telemetry: createTelemetryServiceMock(),
ContainerMetricsTable: () => <div />,
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/infra/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embedd
import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory';
import { createMetricsFetchData, createMetricsHasData } from './metrics_overview_fetchers';
import { registerFeatures } from './register_feature';
import { InventoryViewsService } from './services/inventory_views';
import { LogViewsService } from './services/log_views';
import { TelemetryService } from './services/telemetry';
import {
Expand All @@ -44,12 +45,14 @@ import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_

export class Plugin implements InfraClientPluginClass {
public config: InfraPublicConfig;
private inventoryViews: InventoryViewsService;
private logViews: LogViewsService;
private telemetry: TelemetryService;
private readonly appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));

constructor(context: PluginInitializerContext<InfraPublicConfig>) {
this.config = context.config.get();
this.inventoryViews = new InventoryViewsService();
this.logViews = new LogViewsService({
messageFields:
this.config.sources?.default?.fields?.message ?? defaultLogViewsStaticConfig.messageFields,
Expand Down Expand Up @@ -285,6 +288,10 @@ export class Plugin implements InfraClientPluginClass {
start(core: InfraClientCoreStart, plugins: InfraClientStartDeps) {
const getStartServices = (): InfraClientStartServices => [core, plugins, startContract];

const inventoryViews = this.inventoryViews.start({
http: core.http,
});

const logViews = this.logViews.start({
http: core.http,
dataViews: plugins.dataViews,
Expand All @@ -294,6 +301,7 @@ export class Plugin implements InfraClientPluginClass {
const telemetry = this.telemetry.start();

const startContract: InfraClientStartExports = {
inventoryViews,
logViews,
telemetry,
ContainerMetricsTable: createLazyContainerMetricsTable(getStartServices),
Expand Down
10 changes: 10 additions & 0 deletions x-pack/plugins/infra/public/services/inventory_views/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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_client';
export * from './inventory_views_service';
export * from './types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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 { IInventoryViewsClient } from './types';

export const createInventoryViewsClientMock = (): jest.Mocked<IInventoryViewsClient> => ({
findInventoryViews: jest.fn(),
getInventoryView: jest.fn(),
createInventoryView: jest.fn(),
updateInventoryView: jest.fn(),
deleteInventoryView: jest.fn(),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* 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 { HttpStart } from '@kbn/core/public';
import {
CreateInventoryViewAttributesRequestPayload,
createInventoryViewRequestPayloadRT,
findInventoryViewResponsePayloadRT,
getInventoryViewUrl,
inventoryViewResponsePayloadRT,
UpdateInventoryViewAttributesRequestPayload,
} from '../../../common/http_api/latest';
import {
DeleteInventoryViewError,
FetchInventoryViewError,
InventoryView,
UpsertInventoryViewError,
} from '../../../common/inventory_views';
import { decodeOrThrow } from '../../../common/runtime_types';
import { IInventoryViewsClient } from './types';

export class InventoryViewsClient implements IInventoryViewsClient {
constructor(private readonly http: HttpStart) {}

async findInventoryViews(): Promise<InventoryView[]> {
const response = await this.http.get(getInventoryViewUrl()).catch((error) => {
throw new FetchInventoryViewError(`Failed to fetch inventory views: ${error}`);
});

const { data } = decodeOrThrow(
findInventoryViewResponsePayloadRT,
(message: string) =>
new FetchInventoryViewError(`Failed to decode inventory views: ${message}"`)
)(response);

return data;
}

async getInventoryView(inventoryViewId: string): Promise<InventoryView> {
const response = await this.http.get(getInventoryViewUrl(inventoryViewId)).catch((error) => {
throw new FetchInventoryViewError(
`Failed to fetch inventory view "${inventoryViewId}": ${error}`
);
});

const { data } = decodeOrThrow(
inventoryViewResponsePayloadRT,
(message: string) =>
new FetchInventoryViewError(
`Failed to decode inventory view "${inventoryViewId}": ${message}"`
)
)(response);

return data;
}

async createInventoryView(
inventoryViewAttributes: CreateInventoryViewAttributesRequestPayload
): Promise<InventoryView> {
const response = await this.http
.post(getInventoryViewUrl(), {
body: JSON.stringify(
createInventoryViewRequestPayloadRT.encode({ attributes: inventoryViewAttributes })
),
})
.catch((error) => {
throw new UpsertInventoryViewError(`Failed to create new inventory view : ${error}`);
});

const { data } = decodeOrThrow(
inventoryViewResponsePayloadRT,
(message: string) =>
new UpsertInventoryViewError(`Failed to decode newly written inventory view: ${message}"`)
)(response);

return data;
}

async updateInventoryView(
inventoryViewId: string,
inventoryViewAttributes: UpdateInventoryViewAttributesRequestPayload
): Promise<InventoryView> {
const response = await this.http
.put(getInventoryViewUrl(inventoryViewId), {
body: JSON.stringify(
createInventoryViewRequestPayloadRT.encode({ attributes: inventoryViewAttributes })
),
})
.catch((error) => {
throw new UpsertInventoryViewError(
`Failed to update inventory view "${inventoryViewId}": ${error}`
);
});

const { data } = decodeOrThrow(
inventoryViewResponsePayloadRT,
(message: string) =>
new UpsertInventoryViewError(
`Failed to decode updated inventory view "${inventoryViewId}": ${message}"`
)
)(response);

return data;
}

deleteInventoryView(inventoryViewId: string): Promise<null> {
return this.http
.delete(getInventoryViewUrl(inventoryViewId))
.then(() => null)
.catch((error) => {
throw new DeleteInventoryViewError(
`Failed to delete inventory view "${inventoryViewId}": ${error}`
);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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 { createInventoryViewsClientMock } from './inventory_views_client.mock';
import { InventoryViewsServiceStart } from './types';

export const createInventoryViewsServiceStartMock = () => ({
client: createInventoryViewsClientMock(),
});

export const _ensureTypeCompatibility = (): InventoryViewsServiceStart =>
createInventoryViewsServiceStartMock();
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 { InventoryViewsClient } from './inventory_views_client';
import {
InventoryViewsServiceStartDeps,
InventoryViewsServiceSetup,
InventoryViewsServiceStart,
} from './types';

export class InventoryViewsService {
public setup(): InventoryViewsServiceSetup {}

public start({ http }: InventoryViewsServiceStartDeps): InventoryViewsServiceStart {
const client = new InventoryViewsClient(http);

return {
client,
};
}
}
32 changes: 32 additions & 0 deletions x-pack/plugins/infra/public/services/inventory_views/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 { HttpStart } from '@kbn/core/public';
import { InventoryView, InventoryViewAttributes } from '../../../common/inventory_views';

export type InventoryViewsServiceSetup = void;

export interface InventoryViewsServiceStart {
client: IInventoryViewsClient;
}

export interface InventoryViewsServiceStartDeps {
http: HttpStart;
}

export interface IInventoryViewsClient {
findInventoryViews(): Promise<InventoryView[]>;
getInventoryView(inventoryViewId: string): Promise<InventoryView>;
createInventoryView(
inventoryViewAttributes: Partial<InventoryViewAttributes>
): Promise<InventoryView>;
updateInventoryView(
inventoryViewId: string,
inventoryViewAttributes: Partial<InventoryViewAttributes>
): Promise<InventoryView>;
deleteInventoryView(inventoryViewId: string): Promise<null>;
}
2 changes: 2 additions & 0 deletions x-pack/plugins/infra/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ import type {
SourceProviderProps,
UseNodeMetricsTableOptions,
} from './components/infrastructure_node_metrics_tables/shared';
import { InventoryViewsServiceStart } from './services/inventory_views';
import { LogViewsServiceStart } from './services/log_views';
import { ITelemetryClient } from './services/telemetry';

// Our own setup and start contract values
export type InfraClientSetupExports = void;

export interface InfraClientStartExports {
inventoryViews: InventoryViewsServiceStart;
logViews: LogViewsServiceStart;
telemetry: ITelemetryClient;
ContainerMetricsTable: (
Expand Down

0 comments on commit 1351760

Please sign in to comment.