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

[EEM][POC] The POC for creating entity-centric indices using entity definitions #183205

Merged
merged 17 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
4 changes: 2 additions & 2 deletions x-pack/packages/kbn-oam-schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
* 2.0.
*/

export * from './src/schema/oam_definition';
export * from './src/schema/asset';
export * from './src/schema/entity_definition';
simianhacker marked this conversation as resolved.
Show resolved Hide resolved
export * from './src/schema/entity';
export * from './src/schema/common';
4 changes: 2 additions & 2 deletions x-pack/packages/kbn-oam-schema/src/schema/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { z } from 'zod';
import moment from 'moment';

export enum AssetType {
export enum EntityType {
service = 'service',
host = 'host',
pod = 'pod',
Expand All @@ -17,7 +17,7 @@ export enum AssetType {

export const arrayOfStringsSchema = z.array(z.string());

export const assetTypeSchema = z.nativeEnum(AssetType);
export const entityTypeSchema = z.nativeEnum(EntityType);

export enum BasicAggregations {
avg = 'avg',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
import { z } from 'zod';
import { arrayOfStringsSchema } from './common';

export const assetSchema = z.intersection(
export const entitySchema = z.intersection(
z.object({
asset: z.object({
entity: z.object({
id: z.string(),
indexPattern: arrayOfStringsSchema,
category: arrayOfStringsSchema,
identityField: arrayOfStringsSchema,
indexPatterns: arrayOfStringsSchema,
identityFields: arrayOfStringsSchema,
metric: z.record(z.string(), z.number()),
}),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,22 @@
import { z } from 'zod';
import {
arrayOfStringsSchema,
assetTypeSchema,
entityTypeSchema,
keyMetricSchema,
metadataSchema,
filterSchema,
durationSchema,
} from './common';

export const oamDefinitionSchema = z.object({
export const entityDefinitionSchema = z.object({
id: z.string().regex(/^[\w-]+$/),
name: z.string(),
description: z.optional(z.string()),
type: assetTypeSchema,
type: entityTypeSchema,
filter: filterSchema,
indexPatterns: arrayOfStringsSchema,
identityFields: arrayOfStringsSchema,
identityTemplate: z.string(),
categories: arrayOfStringsSchema,
metadata: z.optional(z.array(metadataSchema)),
metrics: z.optional(z.array(keyMetricSchema)),
staticFields: z.optional(z.record(z.string(), z.string())),
Expand All @@ -39,4 +38,4 @@ export const oamDefinitionSchema = z.object({
),
});

export type OAMDefinition = z.infer<typeof oamDefinitionSchema>;
export type EntityDefinition = z.infer<typeof entityDefinitionSchema>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 const ENTITY_VERSION = 'v1';
export const ENTITY_BASE_PREFIX = `.entities-observability.entity-${ENTITY_VERSION}`;
export const ENTITY_TRANSFORM_PREFIX = `entities-observability-entity-${ENTITY_VERSION}`;
export const ENTITY_DEFAULT_FREQUENCY = '1m';
export const ENTITY_DEFAULT_SYNC_DELAY = '60s';
export const ENTITY_API_PREFIX = '/api/entities';

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
*/

import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { OAMDefinition } from '@kbn/oam-schema';
import { EntityDefinition } from '@kbn/oam-schema';
simianhacker marked this conversation as resolved.
Show resolved Hide resolved
import { generateProcessors } from './ingest_pipeline/generate_processors';
import { retryTransientEsErrors } from './helpers/retry';
import { OAMSecurityException } from './errors/oam_security_exception';
import { EntitySecurityException } from './errors/entity_security_exception';
import { generateIngestPipelineId } from './ingest_pipeline/generate_ingest_pipeline_id';

export async function createAndInstallIngestPipeline(
esClient: ElasticsearchClient,
definition: OAMDefinition,
definition: EntityDefinition,
logger: Logger
) {
const processors = generateProcessors(definition);
Expand All @@ -29,9 +29,9 @@ export async function createAndInstallIngestPipeline(
{ logger }
);
} catch (e) {
logger.error(`Cannot create OAM tranform for [${definition.id}] asset defintion`);
logger.error(`Cannot create entity ingest pipeline for [${definition.id}] entity defintion`);
if (e.meta?.body?.error?.type === 'security_exception') {
throw new OAMSecurityException(e.meta.body.error.reason, definition);
throw new EntitySecurityException(e.meta.body.error.reason, definition);
}
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@
*/

import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { OAMDefinition } from '@kbn/oam-schema';
import { EntityDefinition } from '@kbn/oam-schema';
import { generateTransform } from './transform/generate_transform';
import { retryTransientEsErrors } from './helpers/retry';
import { OAMSecurityException } from './errors/oam_security_exception';
import { EntitySecurityException } from './errors/entity_security_exception';

export async function createAndInstallTransform(
esClient: ElasticsearchClient,
definition: OAMDefinition,
definition: EntityDefinition,
logger: Logger
) {
const transform = generateTransform(definition);
try {
await retryTransientEsErrors(() => esClient.transform.putTransform(transform), { logger });
} catch (e) {
logger.error(`Cannot create OAM transform for [${definition.id}] asset definition`);
logger.error(`Cannot create entity transform for [${definition.id}] entity definition`);
if (e.meta?.body?.error?.type === 'security_exception') {
throw new OAMSecurityException(e.meta.body.error.reason, definition);
throw new EntitySecurityException(e.meta.body.error.reason, definition);
}
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { Logger, SavedObjectsClientContract } from '@kbn/core/server';
import { EntityDefinition } from '@kbn/oam-schema';
import { SO_ENTITY_DEFINITION_TYPE } from '../../saved_objects';
import { EntityDefinitionNotFound } from './errors/entity_not_found';

export async function deleteEntityDefinition(
soClient: SavedObjectsClientContract,
definition: EntityDefinition,
logger: Logger
) {
const response = await soClient.find<EntityDefinition>({
type: SO_ENTITY_DEFINITION_TYPE,
page: 1,
perPage: 1,
filter: `${SO_ENTITY_DEFINITION_TYPE}.attributes.id:(${definition.id})`,
});

if (response.total === 0) {
logger.error(`Unable to delete entity definition [${definition.id}] because it doesn't exist.`);
throw new EntityDefinitionNotFound(`Entity defintion with [${definition.id}] not found.`);
}

await soClient.delete(SO_ENTITY_DEFINITION_TYPE, response.saved_objects[0].id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
*/

import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { OAMDefinition } from '@kbn/oam-schema';
import { EntityDefinition } from '@kbn/oam-schema';
import { generateIndexName } from './helpers/generate_index_name';

export async function deleteIndex(
esClient: ElasticsearchClient,
definition: OAMDefinition,
definition: EntityDefinition,
logger: Logger
) {
const indexName = generateIndexName(definition);
try {
esClient.indices.delete({ index: indexName, ignore_unavailable: true });
await esClient.indices.delete({ index: indexName, ignore_unavailable: true });
} catch (e) {
logger.error(`Unable to remove OAM Defintion index [${definition.id}}]`);
logger.error(`Unable to remove entity defintion index [${definition.id}}]`);
throw e;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
*/

import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { OAMDefinition } from '@kbn/oam-schema';
import { EntityDefinition } from '@kbn/oam-schema';
import { generateIngestPipelineId } from './ingest_pipeline/generate_ingest_pipeline_id';
import { retryTransientEsErrors } from './helpers/retry';

export async function deleteIngestPipeline(
esClient: ElasticsearchClient,
definition: OAMDefinition,
definition: EntityDefinition,
logger: Logger
) {
const pipelineId = generateIngestPipelineId(definition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* 2.0.
*/

import { OAMDefinition } from '@kbn/oam-schema';
import { EntityDefinition } from '@kbn/oam-schema';

export class OAMSecurityException extends Error {
public defintion: OAMDefinition;
export class EntityIdConflict extends Error {
public defintion: EntityDefinition;

constructor(message: string, def: OAMDefinition) {
constructor(message: string, def: EntityDefinition) {
super(message);
this.name = 'OAMSecurityException';
this.name = 'EntityIdConflict';
this.defintion = def;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* 2.0.
*/

export class OAMNotFound extends Error {
export class EntityDefinitionNotFound extends Error {
constructor(message: string) {
super(message);
this.name = 'OAMNotFound';
this.name = 'EntityDefinitionNotFound';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* 2.0.
*/

import { OAMDefinition } from '@kbn/oam-schema';
import { EntityDefinition } from '@kbn/oam-schema';

export class OAMIdConflict extends Error {
public defintion: OAMDefinition;
export class EntitySecurityException extends Error {
public defintion: EntityDefinition;

constructor(message: string, def: OAMDefinition) {
constructor(message: string, def: EntityDefinition) {
super(message);
this.name = 'OAMIdConflict';
this.name = 'EntitySecurityException';
this.defintion = def;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
* 2.0.
*/

import { oamDefinitionSchema } from '@kbn/oam-schema';
export const oamDefinition = oamDefinitionSchema.parse({
import { entityDefinitionSchema } from '@kbn/oam-schema';
export const entityDefinition = entityDefinitionSchema.parse({
id: 'admin-console-logs-service',
name: 'Services for Admin Console',
type: 'service',
indexPatterns: ['kbn-data-forge-fake_stack.*'],
timestampField: '@timestamp',
categories: ['service', 'logs'],
identityFields: ['log.logger'],
identityTemplate: 'service:{{log.logger}}',
metadata: ['tags', 'host.name', 'kubernetes.pod.name'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* 2.0.
*/

import { OAMDefinition } from '@kbn/oam-schema';
import { OAM_BASE_PREFIX } from '../../../../common/constants_oam';
import { EntityDefinition } from '@kbn/oam-schema';
import { ENTITY_BASE_PREFIX } from '../../../../common/constants_entities';

export function generateIndexName(definition: OAMDefinition) {
return `${OAM_BASE_PREFIX}.${definition.id}`;
export function generateIndexName(definition: EntityDefinition) {
return `${ENTITY_BASE_PREFIX}.${definition.id}`;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading