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

[asset manager] merge obsasset signals collection #162222

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0b23894
[Asset Manager] run implicit collection periodically (#156830)
klacabane May 11, 2023
45079fb
[Asset Manager] implicit collection telemetry (#157474)
klacabane May 30, 2023
e8d32ee
Add asset.kind handling to assets API (#159065)
jasonrhodes Jun 6, 2023
b93feb5
Add asset source switching config (#159338)
jasonrhodes Jun 9, 2023
673ce4d
Adds getHosts method and GET /assets/hosts endpoint (#159357)
jasonrhodes Jun 12, 2023
d965cd5
[Asset Manager] query pagination (#159693)
klacabane Jun 20, 2023
77a9c6a
[asset manager] move collectors outside of implicit collection dir (#…
klacabane Jul 18, 2023
9d263ce
[asset manager] remove sync apm span (#162180)
klacabane Jul 19, 2023
9f3a2c3
remove implicit collection code
klacabane Jul 19, 2023
e45ab38
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jul 19, 2023
3a4398a
delete unused constants
klacabane Jul 19, 2023
dbbeaab
Merge branch 'main' into 161887-merge-obsasset-signals-collection
klacabane Jul 19, 2023
18e2f0d
enable ftr suite
klacabane Jul 19, 2023
342d60c
conditionally skip test
klacabane Jul 20, 2023
234796f
Merge branch 'main' into 161887-merge-obsasset-signals-collection
kibanamachine Aug 15, 2023
dc1db85
split signals/assets ftr configs
klacabane Aug 16, 2023
b1e2a96
cleanup
klacabane Aug 16, 2023
d059c88
Merge branch 'main' into 161887-merge-obsasset-signals-collection
klacabane Aug 16, 2023
cf934ec
Merge branch 'main' into 161887-merge-obsasset-signals-collection
klacabane Aug 16, 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
26 changes: 20 additions & 6 deletions x-pack/plugins/asset_manager/common/types_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ export const assetTypeRT = rt.union([

export type AssetType = rt.TypeOf<typeof assetTypeRT>;

export type AssetKind = 'unknown' | 'node';
export const assetKindRT = rt.union([
rt.literal('cluster'),
rt.literal('host'),
rt.literal('pod'),
rt.literal('container'),
rt.literal('service'),
rt.literal('alert'),
]);

export type AssetKind = rt.TypeOf<typeof assetKindRT>;

export type AssetStatus =
| 'CREATING'
| 'ACTIVE'
Expand Down Expand Up @@ -47,17 +57,20 @@ export interface ECSDocument extends WithTimestamp {
'orchestrator.cluster.version'?: string;

'cloud.provider'?: CloudProviderName;
'cloud.instance.id'?: string;
'cloud.region'?: string;
'cloud.service.name'?: string;

'service.environment'?: string;
}

export interface Asset extends ECSDocument {
'asset.collection_version'?: string;
'asset.ean': string;
'asset.id': string;
'asset.kind'?: AssetKind;
'asset.kind': AssetKind;
'asset.name'?: string;
'asset.type': AssetType;
'asset.type'?: AssetType;
'asset.status'?: AssetStatus;
'asset.parents'?: string | string[];
'asset.children'?: string | string[];
Expand Down Expand Up @@ -121,14 +134,15 @@ export interface K8sCluster extends WithTimestamp {

export interface AssetFilters {
type?: AssetType | AssetType[];
kind?: AssetKind;
kind?: AssetKind | AssetKind[];
ean?: string | string[];
id?: string;
typeLike?: string;
kindLike?: string;
eanLike?: string;
collectionVersion?: number | 'latest' | 'all';
from?: string;
to?: string;
from?: string | number;
to?: string | number;
}

export const relationRT = rt.union([
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/asset_manager/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
*/

import { PluginInitializerContext } from '@kbn/core-plugins-server';
import { AssetManagerServerPlugin, config, AssetManagerConfig } from './plugin';
import { AssetManagerServerPlugin, config } from './plugin';
import type { WriteSamplesPostBody } from './routes/sample_assets';
import { AssetManagerConfig } from './types';

export type { AssetManagerConfig, WriteSamplesPostBody };
export { config };
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 { GetHostsOptionsInjected } from '.';
import { getAssets } from '../../get_assets';

export async function getHostsByAssets(
options: GetHostsOptionsInjected
): Promise<{ hosts: Asset[] }> {
const hosts = await getAssets({
esClient: options.esClient,
filters: {
kind: 'host',
from: options.from,
to: options.to,
},
});

return {
hosts,
};
}
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 { Asset } from '../../../../common/types_api';
import { GetHostsOptionsInjected } from '.';
import { collectHosts } from '../../collectors/hosts';

export async function getHostsBySignals(
options: GetHostsOptionsInjected
): Promise<{ hosts: Asset[] }> {
const { assets } = await collectHosts({
client: options.esClient,
from: options.from,
to: options.to,
sourceIndices: options.sourceIndices,
});
return {
hosts: assets,
};
}
20 changes: 20 additions & 0 deletions x-pack/plugins/asset_manager/server/lib/accessors/hosts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 { AccessorOptions, OptionsWithInjectedValues } from '..';

export interface GetHostsOptions extends AccessorOptions {
from: number;
to: number;
}
export type GetHostsOptionsInjected = OptionsWithInjectedValues<GetHostsOptions>;

export interface HostIdentifier {
'asset.ean': string;
'asset.id': string;
'asset.name'?: string;
}
19 changes: 19 additions & 0 deletions x-pack/plugins/asset_manager/server/lib/accessors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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 { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { AssetManagerConfig } from '../../types';

export interface InjectedValues {
sourceIndices: AssetManagerConfig['sourceIndices'];
}

export type OptionsWithInjectedValues<T extends object> = T & InjectedValues;

export interface AccessorOptions {
esClient: ElasticsearchClient;
}
38 changes: 38 additions & 0 deletions x-pack/plugins/asset_manager/server/lib/asset_accessor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 { AssetManagerConfig } from '../types';
import { OptionsWithInjectedValues } from './accessors';
import { GetHostsOptions } from './accessors/hosts';
import { getHostsByAssets } from './accessors/hosts/get_hosts_by_assets';
import { getHostsBySignals } from './accessors/hosts/get_hosts_by_signals';

interface AssetAccessorClassOptions {
sourceIndices: AssetManagerConfig['sourceIndices'];
source: AssetManagerConfig['lockedSource'];
}

export class AssetAccessor {
constructor(private options: AssetAccessorClassOptions) {}

injectOptions<T extends object = {}>(options: T): OptionsWithInjectedValues<T> {
return {
...options,
sourceIndices: this.options.sourceIndices,
};
}

async getHosts(options: GetHostsOptions): Promise<{ hosts: Asset[] }> {
const withInjected = this.injectOptions(options);
if (this.options.source === 'assets') {
return await getHostsByAssets(withInjected);
} else {
return await getHostsBySignals(withInjected);
}
}
}
91 changes: 91 additions & 0 deletions x-pack/plugins/asset_manager/server/lib/collectors/containers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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 { estypes } from '@elastic/elasticsearch';
import { Asset } from '../../../common/types_api';
import { CollectorOptions, QUERY_MAX_SIZE } from '.';

export async function collectContainers({
client,
from,
to,
sourceIndices,
afterKey,
}: CollectorOptions) {
const { metrics, logs, traces } = sourceIndices;
const dsl: estypes.SearchRequest = {
index: [traces, logs, metrics],
size: QUERY_MAX_SIZE,
collapse: {
field: 'container.id',
},
sort: [{ 'container.id': 'asc' }],
_source: false,
fields: [
'kubernetes.*',
'cloud.provider',
'orchestrator.cluster.name',
'host.name',
'host.hostname',
],
query: {
bool: {
filter: [
{
range: {
'@timestamp': {
gte: from,
lte: to,
},
},
},
],
should: [
{ exists: { field: 'kubernetes.container.id' } },
{ exists: { field: 'kubernetes.pod.uid' } },
{ exists: { field: 'kubernetes.node.name' } },
{ exists: { field: 'host.hostname' } },
],
},
},
};

if (afterKey) {
dsl.search_after = afterKey;
}

const esResponse = await client.search(dsl);

const assets = esResponse.hits.hits.reduce<Asset[]>((acc: Asset[], hit: any) => {
const { fields = {} } = hit;
const containerId = fields['container.id'];
const podUid = fields['kubernetes.pod.uid'];
const nodeName = fields['kubernetes.node.name'];

const parentEan = podUid ? `pod:${podUid}` : `host:${fields['host.hostname']}`;

const container: Asset = {
'@timestamp': new Date().toISOString(),
'asset.kind': 'container',
'asset.id': containerId,
'asset.ean': `container:${containerId}`,
'asset.parents': [parentEan],
};

if (nodeName) {
container['asset.references'] = [`host:${nodeName}`];
}

acc.push(container);

return acc;
}, []);

const hitsLen = esResponse.hits.hits.length;
const next = hitsLen === QUERY_MAX_SIZE ? esResponse.hits.hits[hitsLen - 1].sort : undefined;
return { assets, afterKey: next };
}
Loading