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

Get the assetClient ready for building inventory prototype #167692

Merged
merged 13 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ disabled:
- x-pack/test/plugin_api_perf/config.js
- x-pack/test/screenshot_creation/config.ts
- x-pack/test/fleet_packages/config.ts
- x-pack/test/api_integration/apis/asset_manager/config_with_assets_source.ts

# Scalability testing config that we run in its own pipeline
- x-pack/test/scalability/config.ts
Expand Down Expand Up @@ -175,7 +174,7 @@ enabled:
- x-pack/test/api_integration/config_security_trial.ts
- x-pack/test/api_integration/apis/aiops/config.ts
- x-pack/test/api_integration/apis/asset_manager/config_when_disabled.ts
- x-pack/test/api_integration/apis/asset_manager/config_with_signals_source.ts
- x-pack/test/api_integration/apis/asset_manager/config_when_enabled.ts
- x-pack/test/api_integration/apis/cases/config.ts
- x-pack/test/api_integration/apis/cloud_security_posture/config.ts
- x-pack/test/api_integration/apis/console/config.ts
Expand Down
8 changes: 0 additions & 8 deletions x-pack/plugins/asset_manager/common/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,6 @@ export const configSchema = schema.object({
},
{ defaultValue: INDEX_DEFAULTS }
),
// Choose an explicit source for asset queries.
// NOTE: This will eventually need to be able to cleverly switch
// between these values based on the availability of data in the
// indices, and possibly for each asset kind/type value.
// For now, we set this explicitly.
lockedSource: schema.oneOf([schema.literal('assets'), schema.literal('signals')], {
defaultValue: 'signals',
}),
});

export type AssetManagerConfig = TypeOf<typeof configSchema>;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/asset_manager/common/constants_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export const GET_RELATED_ASSETS = base('/assets/related');
export const GET_ASSETS_DIFF = base('/assets/diff');

export const GET_HOSTS = base('/assets/hosts');
export const GET_SERVICES = base('/assets/services');
23 changes: 22 additions & 1 deletion x-pack/plugins/asset_manager/common/types_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ export const sizeRT = rt.union([
createLiteralValueFromUndefinedRT(10),
]);
export const assetDateRT = rt.union([dateRt, datemathStringRt]);

/**
* Hosts
*/
export const getHostAssetsQueryOptionsRT = rt.exact(
rt.partial({
from: assetDateRT,
Expand All @@ -204,8 +208,25 @@ export const getHostAssetsQueryOptionsRT = rt.exact(
})
);
export type GetHostAssetsQueryOptions = rt.TypeOf<typeof getHostAssetsQueryOptionsRT>;

export const getHostAssetsResponseRT = rt.type({
hosts: rt.array(assetRT),
});
export type GetHostAssetsResponse = rt.TypeOf<typeof getHostAssetsResponseRT>;

/**
* Services
*/
export const getServiceAssetsQueryOptionsRT = rt.exact(
rt.partial({
from: assetDateRT,
to: assetDateRT,
size: sizeRT,
parent: rt.string,
})
);

export type GetServiceAssetsQueryOptions = rt.TypeOf<typeof getServiceAssetsQueryOptionsRT>;
export const getServiceAssetsResponseRT = rt.type({
services: rt.array(assetRT),
});
export type GetServiceAssetsResponse = rt.TypeOf<typeof getServiceAssetsResponseRT>;
10 changes: 5 additions & 5 deletions x-pack/plugins/asset_manager/common/types_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
* 2.0.
*/

export interface GetHostsOptionsPublic {
export interface SharedAssetsOptionsPublic {
from: string;
to: string;
to?: string;
}

export interface GetServicesOptionsPublic {
from: string;
to: string;
export type GetHostsOptionsPublic = SharedAssetsOptionsPublic;

export interface GetServicesOptionsPublic extends SharedAssetsOptionsPublic {
parent?: string;
}
24 changes: 22 additions & 2 deletions x-pack/plugins/asset_manager/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,11 @@ it will be able to pull the properly-scoped client dependencies off of that requ

### Client methods

TODO: Link to a centralized asset document example that each response can reference?

#### getHosts

Get a group of host assets found within a specified time range.
Get a list of host assets found within a specified time range.

| Parameter | Type | Required? | Description |
| :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- |
Expand All @@ -184,4 +186,22 @@ Get a group of host assets found within a specified time range.
}
```

TODO: Link to a centralized asset document example that each response can reference?
#### getServices

Get a list of service assets found within a specified time range.

| Parameter | Type | Required? | Description |
| :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- |
| from | datetime string | yes | ISO date string representing the START of the time range being queried |
| to | datetime string | yes | ISO date string representing the END of the time range being queried |
| parent | string | no | EAN value for a given parent service to filter services by |

**Response**

```json
{
"services": [
...found service assets
]
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,40 @@ describe('Public assets client', () => {

it('should return the direct results of http.get', async () => {
const client = new PublicAssetsClient(http);
http.get.mockResolvedValueOnce('my result');
http.get.mockResolvedValueOnce('my hosts');
const result = await client.getHosts({ from: 'x', to: 'y' });
expect(result).toBe('my result');
expect(result).toBe('my hosts');
});
});

describe('getServices', () => {
it('should call the REST API', async () => {
const client = new PublicAssetsClient(http);
await client.getServices({ from: 'x', to: 'y' });
expect(http.get).toBeCalledTimes(1);
});

it('should include specified "from" and "to" parameters in http.get query', async () => {
const client = new PublicAssetsClient(http);
await client.getServices({ from: 'x', to: 'y' });
expect(http.get).toBeCalledWith(routePaths.GET_SERVICES, {
query: { from: 'x', to: 'y' },
});
});

it('should include specified "parent" parameter in http.get query', async () => {
const client = new PublicAssetsClient(http);
await client.getServices({ from: 'x', to: 'y', parent: 'container:123' });
expect(http.get).toBeCalledWith(routePaths.GET_SERVICES, {
query: { from: 'x', to: 'y', parent: 'container:123' },
});
});

it('should return the direct results of http.get', async () => {
const client = new PublicAssetsClient(http);
http.get.mockResolvedValueOnce('my services');
const result = await client.getServices({ from: 'x', to: 'y' });
expect(result).toBe('my services');
});
});
});
16 changes: 13 additions & 3 deletions x-pack/plugins/asset_manager/public/lib/public_assets_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
*/

import { HttpStart } from '@kbn/core/public';
import { GetHostsOptionsPublic } from '../../common/types_client';
import { GetHostAssetsResponse } from '../../common/types_api';
import { GET_HOSTS } from '../../common/constants_routes';
import { GetHostsOptionsPublic, GetServicesOptionsPublic } from '../../common/types_client';
import { GetHostAssetsResponse, GetServiceAssetsResponse } from '../../common/types_api';
import { GET_HOSTS, GET_SERVICES } from '../../common/constants_routes';
import { IPublicAssetsClient } from '../types';

export class PublicAssetsClient implements IPublicAssetsClient {
Expand All @@ -23,4 +23,14 @@ export class PublicAssetsClient implements IPublicAssetsClient {

return results;
}

async getServices(options: GetServicesOptionsPublic) {
const results = await this.http.get<GetServiceAssetsResponse>(GET_SERVICES, {
query: {
...options,
},
});

return results;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,25 @@
*/

import { Asset } from '../../../../common/types_api';
import { GetHostsOptionsInjected } from '.';
import { collectHosts } from '../../collectors/hosts';
import { GetHostsOptionsPublic } from '../../../../common/types_client';
import {
AssetClientDependencies,
AssetClientOptionsWithInjectedValues,
} from '../../asset_client_types';

export async function getHostsBySignals(
options: GetHostsOptionsInjected
): Promise<{ hosts: Asset[] }> {
export type GetHostsOptions = GetHostsOptionsPublic & AssetClientDependencies;
export type GetHostsOptionsInjected = AssetClientOptionsWithInjectedValues<GetHostsOptions>;

export async function getHosts(options: GetHostsOptionsInjected): Promise<{ hosts: Asset[] }> {
const metricsIndices = await options.metricsClient.getMetricIndices({
savedObjectsClient: options.savedObjectsClient,
});

const { assets } = await collectHosts({
client: options.elasticsearchClient,
from: options.from,
to: options.to,
to: options.to || 'now',
sourceIndices: {
metrics: metricsIndices,
logs: options.sourceIndices.logs,
Expand Down

This file was deleted.

19 changes: 0 additions & 19 deletions x-pack/plugins/asset_manager/server/lib/accessors/hosts/index.ts

This file was deleted.

19 changes: 0 additions & 19 deletions x-pack/plugins/asset_manager/server/lib/accessors/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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 { Asset } from '../../../../common/types_api';
import { collectServices } from '../../collectors/services';
import { parseEan } from '../../parse_ean';
import { GetServicesOptionsPublic } from '../../../../common/types_client';
import {
AssetClientDependencies,
AssetClientOptionsWithInjectedValues,
} from '../../asset_client_types';

export type GetServicesOptions = GetServicesOptionsPublic & AssetClientDependencies;
export type GetServicesOptionsInjected = AssetClientOptionsWithInjectedValues<GetServicesOptions>;

export async function getServices(
options: GetServicesOptionsInjected
): Promise<{ services: Asset[] }> {
const filters = [];

if (options.parent) {
const { kind, id } = parseEan(options.parent);
Copy link
Contributor

@klacabane klacabane Oct 4, 2023

Choose a reason for hiding this comment

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

should we validate kind value as part of parseEan (caller can pass the supported types to the function), or here, maybe with a switch ? thinking the api consumer should know if the parameter was ignored

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. I think I'll explore this more as I develop the UI built on top of it, and see what makes the most sense.


if (kind === 'host') {
filters.push({
bool: {
should: [{ term: { 'host.name': id } }, { term: { 'host.hostname': id } }],
minimum_should_match: 1,
},
});
}

if (kind === 'container') {
filters.push({
bool: {
should: [{ term: { 'container.id': id } }],
minimum_should_match: 1,
},
});
}
}

const apmIndices = await options.getApmIndices(options.savedObjectsClient);
const { assets } = await collectServices({
client: options.elasticsearchClient,
from: options.from,
to: options.to || 'now',
sourceIndices: {
apm: apmIndices,
},
filters,
});

return { services: assets };
}
Loading