Skip to content

Commit

Permalink
Merge branch 'main' of github.com:elastic/kibana
Browse files Browse the repository at this point in the history
  • Loading branch information
jennypavlova committed Jan 8, 2025
2 parents 299b233 + 24f8888 commit 57c5eac
Show file tree
Hide file tree
Showing 49 changed files with 618 additions and 828 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"filter_path": [],
"human": "__flag__",
"pretty": "__flag__",
"list_executed_pipelines": "__flag__",
"pipeline": "",
"refresh": [
"true",
Expand All @@ -25,7 +26,8 @@
"all",
"index-setting"
],
"require_alias": "__flag__"
"require_alias": "__flag__",
"require_data_stream": "__flag__"
},
"methods": [
"POST",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"total_feature_importance",
"definition_status"
],
"include_model_definition": "__flag__",
"size": [
"100"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
"error_trace": "__flag__",
"filter_path": [],
"human": "__flag__",
"pretty": "__flag__"
"pretty": "__flag__",
"allow_no_indices": "__flag__",
"expand_wildcards": [
"all",
"open",
"closed",
"hidden",
"none"
],
"ignore_throttled": "__flag__",
"ignore_unavailable": "__flag__"
},
"methods": [
"PUT"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const commonEntityFields: EntityInstance = {
} as EntityInstance['entity'],
};

type Entity = { [key: string]: any } & { entityIdentityFields: { [key: string]: string[] } };

describe('EntityClient', () => {
let entityClient: EntityClient;

Expand All @@ -27,127 +29,103 @@ describe('EntityClient', () => {

describe('asKqlFilter', () => {
it('should return the kql filter', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['service.name', 'service.environment'],
type: 'service',
},
service: {
name: 'my-service',
},
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['service.name', 'service.environment'] },
type: 'service',
['service.name']: 'my-service',
};

const result = entityClient.asKqlFilter(entityLatest);
const result = entityClient.asKqlFilter({ entity });
expect(result).toEqual('service.name: "my-service"');
});

it('should return the kql filter when an indentity field value contain special characters', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['host.name', 'foo.bar'],
},
host: {
name: 'my-host:some-value:some-other-value',
},
it('should return the kql filter when an identity field value contain special characters', () => {
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['host.name', 'foo.bar'] },
type: 'service',
['host.name']: 'my-host:some-value:some-other-value',
};

const result = entityClient.asKqlFilter(entityLatest);
const result = entityClient.asKqlFilter({ entity });
expect(result).toEqual('host.name: "my-host:some-value:some-other-value"');
});

it('should return the kql filter when indentity_fields is composed by multiple fields', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['service.name', 'service.environment'],
type: 'service',
},
service: {
name: 'my-service',
environment: 'staging',
},
it('should return the kql filter when identity_fields is composed by multiple fields', () => {
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['service.name', 'service.environment'] },
type: 'service',
['service.name']: 'my-service',
['service.environment']: 'staging',
};

const result = entityClient.asKqlFilter(entityLatest);
const result = entityClient.asKqlFilter({ entity });
expect(result).toEqual('(service.name: "my-service" AND service.environment: "staging")');
});

it('should ignore fields that are not present in the entity', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['host.name', 'foo.bar'],
},
host: {
name: 'my-host',
},
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['host.name', 'foo.bar'] },
['host.name']: 'my-host',
};

const result = entityClient.asKqlFilter(entityLatest);
const result = entityClient.asKqlFilter({ entity });
expect(result).toEqual('host.name: "my-host"');
});
});

describe('getIdentityFieldsValue', () => {
it('should return identity fields values', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['service.name', 'service.environment'],
type: 'service',
},
service: {
name: 'my-service',
},
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['service.name', 'service.environment'] },
type: 'service',
['service.name']: 'my-service',
};

expect(entityClient.getIdentityFieldsValue(entityLatest)).toEqual({
expect(entityClient.getIdentityFieldsValue({ entity })).toEqual({
'service.name': 'my-service',
});
});

it('should return identity fields values when indentity_fields is composed by multiple fields', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['service.name', 'service.environment'],
type: 'service',
},
service: {
name: 'my-service',
environment: 'staging',
},
it('should return identity fields values when identity_fields is composed by multiple fields', () => {
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['service.name', 'service.environment'] },
type: 'service',
['service.name']: 'my-service',
['service.environment']: 'staging',
};

expect(entityClient.getIdentityFieldsValue(entityLatest)).toEqual({
expect(entityClient.getIdentityFieldsValue({ entity })).toEqual({
'service.name': 'my-service',
'service.environment': 'staging',
});
});

it('should return identity fields when field is in the root', () => {
const entityLatest: EntityInstance = {
entity: {
...commonEntityFields.entity,
identity_fields: ['name'],
type: 'service',
},
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: { source1: ['name'] },
type: 'service',
name: 'foo',
};

expect(entityClient.getIdentityFieldsValue(entityLatest)).toEqual({
expect(entityClient.getIdentityFieldsValue({ entity })).toEqual({
name: 'foo',
});
});

it('should throw an error when identity fields are missing', () => {
const entityLatest: EntityInstance = {
...commonEntityFields,
const entity: Entity = {
...commonEntityFields.entity,
entityIdentityFields: {},
};

expect(() => entityClient.getIdentityFieldsValue(entityLatest)).toThrow(
expect(() => entityClient.getIdentityFieldsValue({ entity })).toThrow(
'Identity fields are missing'
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import {
isHttpFetchError,
} from '@kbn/server-route-repository-client';
import { type KueryNode, nodeTypes, toKqlExpression } from '@kbn/es-query';
import type { EntityDefinition, EntityInstance, EntityMetadata } from '@kbn/entities-schema';
import { castArray } from 'lodash';
import type { EntityDefinition } from '@kbn/entities-schema';
import type { EntityDefinitionWithState } from '../../server/lib/entities/types';
import {
DisableManagedEntityResponse,
Expand Down Expand Up @@ -106,12 +105,12 @@ export class EntityClient {
}
}

asKqlFilter(
entityInstance: {
entity: Pick<EntityInstance['entity'], 'identity_fields'>;
} & Required<EntityMetadata>
) {
const identityFieldsValue = this.getIdentityFieldsValue(entityInstance);
asKqlFilter({
entity,
}: {
entity: { [key: string]: any } & { entityIdentityFields: { [key: string]: string[] } };
}) {
const identityFieldsValue = this.getIdentityFieldsValue({ entity });

const nodes: KueryNode[] = Object.entries(identityFieldsValue).map(([identityField, value]) => {
return nodeTypes.function.buildNode('is', identityField, `"${value}"`);
Expand All @@ -124,26 +123,22 @@ export class EntityClient {
return toKqlExpression(kqlExpression);
}

getIdentityFieldsValue(
entityInstance: {
entity: Pick<EntityInstance['entity'], 'identity_fields'>;
} & Required<EntityMetadata>
) {
const { identity_fields: identityFields } = entityInstance.entity;

if (!identityFields) {
getIdentityFieldsValue({
entity,
}: {
entity: { [key: string]: any } & { entityIdentityFields: { [key: string]: string[] } };
}): Record<string, any> {
const { entityIdentityFields: identityFields } = entity;
if (!Object.keys(identityFields || {}).length) {
throw new Error('Identity fields are missing');
}

return castArray(identityFields).reduce((acc, field) => {
const value = field.split('.').reduce((obj: any, part: string) => {
return obj && typeof obj === 'object' ? (obj as Record<string, any>)[part] : undefined;
}, entityInstance);

if (value) {
acc[field] = value;
}

return Object.values(identityFields).reduce((acc: Record<string, any>, fields) => {
fields.forEach((field) => {
if (entity?.[field]) {
acc[field] = entity[field];
}
});
return acc;
}, {} as Record<string, string>);
}
Expand Down
Loading

0 comments on commit 57c5eac

Please sign in to comment.