mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Upgrade ES client to 9.0.0-alpha.4 (#213375)
## Summary Upgrading the ES client to v9.0.0-alpha.4 to test the changes mentioned in https://github.com/elastic/elasticsearch-js/issues/2584 This new version introduces some type changes, most notably, the `FieldValue` is `string | number | boolean | null | undefined` instead of `any`, leading to some new type checks to be implemented (like on aggregation results `bucket.key`, `search_after`, and `sort` options). On top of that, it adds the new behavior where unknown properties are placed in the `body` (when the request has a body). If they must be in as a query parameter, they should be placed under the `querystring` option. cc @JoshMock TODO: - [x] Stabilize the type errors - [x] Address all the query parameters that are now placed in the body (by wrapping them inside the option `querystring: {}`) I will address `// @ts-expect-error elasticsearch@9.0.0 https://github.com/elastic/elasticsearch-js/issues/2584` in a separate PR to reduce noise. Related https://github.com/elastic/kibana/pull/208776
This commit is contained in:
parent
5d16e44e79
commit
b5ad8bc00b
58 changed files with 128 additions and 106 deletions
|
@ -123,7 +123,7 @@
|
|||
"@elastic/datemath": "5.0.3",
|
||||
"@elastic/ebt": "^1.1.1",
|
||||
"@elastic/ecs": "^8.11.5",
|
||||
"@elastic/elasticsearch": "9.0.0-alpha.3",
|
||||
"@elastic/elasticsearch": "9.0.0-alpha.4",
|
||||
"@elastic/ems-client": "8.6.3",
|
||||
"@elastic/eui": "101.0.1",
|
||||
"@elastic/eui-theme-borealis": "0.1.0",
|
||||
|
|
|
@ -19,6 +19,7 @@ const omittedProps = [
|
|||
'transport',
|
||||
'serializer',
|
||||
'helpers',
|
||||
'acceptedParams',
|
||||
] as Array<PublicKeys<Client>>;
|
||||
|
||||
export type DeeplyMockedApi<T> = {
|
||||
|
|
|
@ -159,7 +159,7 @@ export const performCreate = async <T>(
|
|||
refresh,
|
||||
document: raw._source,
|
||||
...(overwrite && version ? decodeRequestVersion(version) : {}),
|
||||
require_alias: true,
|
||||
querystring: { require_alias: true },
|
||||
};
|
||||
|
||||
const { body, statusCode, headers } =
|
||||
|
|
|
@ -194,8 +194,7 @@ export const executeUpdate = async <T>(
|
|||
refresh,
|
||||
document: rawUpsert._source,
|
||||
...(version ? decodeRequestVersion(version) : {}),
|
||||
// @ts-expect-error
|
||||
require_alias: true,
|
||||
querystring: { require_alias: true },
|
||||
};
|
||||
|
||||
const {
|
||||
|
|
|
@ -1424,7 +1424,7 @@ describe('CsvGenerator', () => {
|
|||
expect(mockEsClient.asCurrentUser.openPointInTime).toHaveBeenCalledWith(
|
||||
{
|
||||
ignore_unavailable: true,
|
||||
ignore_throttled: false,
|
||||
querystring: { ignore_throttled: false },
|
||||
index: 'logstash-*',
|
||||
keep_alive: '30s',
|
||||
},
|
||||
|
|
|
@ -47,13 +47,13 @@ export class SearchCursorPit extends SearchCursor {
|
|||
index: this.indexPatternTitle,
|
||||
keep_alive: scroll.duration(taskInstanceFields),
|
||||
ignore_unavailable: true,
|
||||
// @ts-expect-error ignore_throttled is not in the type definition, but it is accepted by es
|
||||
ignore_throttled: includeFrozen ? false : undefined, // "true" will cause deprecation warnings logged in ES
|
||||
...(includeFrozen ? { querystring: { ignore_throttled: false } } : {}), // "true" will cause deprecation warnings logged in ES
|
||||
},
|
||||
{
|
||||
signal: this.abortController.signal,
|
||||
requestTimeout: scroll.duration(taskInstanceFields),
|
||||
maxRetries: 0,
|
||||
// @ts-expect-error not documented in the types. Is this still supported?
|
||||
maxConcurrentShardRequests,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -115,11 +115,12 @@ export function registerFavoritesUsageCollection({
|
|||
[]) as estypes.AggregationsStringTermsBucket[];
|
||||
|
||||
typesBuckets.forEach((bucket) => {
|
||||
favoritesUsage[bucket.key] = {
|
||||
total: bucket.stats.sum,
|
||||
total_users_spaces: bucket.stats.count,
|
||||
avg_per_user_per_space: bucket.stats.avg,
|
||||
max_per_user_per_space: bucket.stats.max,
|
||||
const stats = bucket.stats as estypes.AggregationsStatsAggregate;
|
||||
favoritesUsage[`${bucket.key}`] = {
|
||||
total: stats.sum,
|
||||
total_users_spaces: stats.count,
|
||||
avg_per_user_per_space: stats.avg!,
|
||||
max_per_user_per_space: stats.max!,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -51,17 +51,19 @@ export const isValidFeatureId = (a: unknown): a is ValidFeatureId =>
|
|||
* @param sortIds estypes.SortResults | undefined
|
||||
* @returns SortResults
|
||||
*/
|
||||
export const getSafeSortIds = (sortIds: estypes.SortResults | null | undefined) => {
|
||||
export const getSafeSortIds = (
|
||||
sortIds: estypes.SortResults | null | undefined
|
||||
): Array<string | number> | undefined => {
|
||||
if (sortIds == null) {
|
||||
return sortIds;
|
||||
return sortIds as undefined;
|
||||
}
|
||||
return sortIds.map((sortId) => {
|
||||
// haven't determined when we would receive a null value for a sort id
|
||||
// but in case we do, default to sending the stringified Java max_int
|
||||
if (sortId == null || sortId === '' || sortId >= Number.MAX_SAFE_INTEGER) {
|
||||
if (sortId == null || sortId === '' || Number(sortId) >= Number.MAX_SAFE_INTEGER) {
|
||||
return '9223372036854775807';
|
||||
}
|
||||
return sortId;
|
||||
return sortId as string | number;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -80,9 +80,10 @@ export async function getSavedObjectsCounts(
|
|||
const nonExpectedTypes: string[] = [];
|
||||
|
||||
const perType = buckets.map((perTypeEntry) => {
|
||||
if (perTypeEntry.key !== MISSING_TYPE_KEY && !soTypes.includes(perTypeEntry.key)) {
|
||||
const key = perTypeEntry.key as string;
|
||||
if (key !== MISSING_TYPE_KEY && !soTypes.includes(key)) {
|
||||
// If the breakdown includes any SO types that are not expected, highlight them in the nonExpectedTypes list.
|
||||
nonExpectedTypes.push(perTypeEntry.key);
|
||||
nonExpectedTypes.push(key);
|
||||
}
|
||||
|
||||
return { key: perTypeEntry.key, doc_count: perTypeEntry.doc_count };
|
||||
|
@ -90,6 +91,7 @@ export async function getSavedObjectsCounts(
|
|||
|
||||
return {
|
||||
total: body.total,
|
||||
// @ts-expect-error `FieldValue` types now claim that bucket keys can be `null`
|
||||
per_type: perType,
|
||||
non_expected_types: nonExpectedTypes,
|
||||
others: body.aggregations?.types?.sum_other_doc_count ?? 0,
|
||||
|
|
|
@ -314,7 +314,9 @@ describe('ES search strategy', () => {
|
|||
expect(mockRollupSearchCaller).toHaveBeenCalledWith(
|
||||
{
|
||||
index: 'foo-程',
|
||||
ignore_unavailable: true,
|
||||
querystring: {
|
||||
ignore_unavailable: true,
|
||||
},
|
||||
max_concurrent_shard_requests: undefined,
|
||||
timeout: '100ms',
|
||||
track_total_hits: true,
|
||||
|
|
|
@ -166,12 +166,20 @@ export const enhancedEsSearchStrategyProvider = (
|
|||
throw new KbnSearchError(`"params.index" is required when performing a rollup search`, 400);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { ignore_unavailable, preference, ...params } = {
|
||||
...querystring,
|
||||
...request.params,
|
||||
index: request.params.index,
|
||||
};
|
||||
|
||||
try {
|
||||
const esResponse = await client.rollup.rollupSearch(
|
||||
{
|
||||
...querystring,
|
||||
...request.params,
|
||||
index: request.params.index,
|
||||
...params,
|
||||
// Not defined in the spec, and the client places it in the body.
|
||||
// This workaround allows us to force it as a query parameter.
|
||||
querystring: { ...params.querystring, ignore_unavailable, preference },
|
||||
},
|
||||
{
|
||||
signal: options?.abortSignal,
|
||||
|
|
|
@ -38,7 +38,7 @@ export const getSavedObjectCounts = async ({
|
|||
(body.aggregations?.types?.buckets as estypes.AggregationsStringTermsBucketKeys[]) || [];
|
||||
|
||||
const counts = buckets.reduce((memo, bucket) => {
|
||||
memo[bucket.key] = bucket.doc_count;
|
||||
memo[`${bucket.key}`] = bucket.doc_count;
|
||||
return memo;
|
||||
}, {} as Record<string, number>);
|
||||
|
||||
|
|
|
@ -162,7 +162,6 @@ const indexWithLifecyclePhaseDefinition: Index = {
|
|||
step_time_millis: 1544187776208,
|
||||
phase_execution: {
|
||||
policy: 'testy',
|
||||
// @ts-expect-error ILM type is incorrect https://github.com/elastic/elasticsearch-specification/issues/2326
|
||||
phase_definition: { min_age: '0s', actions: { rollover: { max_size: '1gb' } } },
|
||||
version: 1,
|
||||
modified_date_in_millis: 1544031699844,
|
||||
|
|
|
@ -83,7 +83,7 @@ export const IndexLifecycleSummary: FunctionComponent<Props> = ({
|
|||
defaultMessage: 'Policy name',
|
||||
}
|
||||
),
|
||||
description: ilm.policy,
|
||||
description: ilm.policy!,
|
||||
},
|
||||
{
|
||||
title: i18n.translate(
|
||||
|
@ -153,7 +153,7 @@ export const IndexLifecycleSummary: FunctionComponent<Props> = ({
|
|||
<EuiLink
|
||||
color="primary"
|
||||
href={getUrlForApp('management', {
|
||||
path: `data/index_lifecycle_management/${getPolicyEditPath(ilm.policy)}`,
|
||||
path: `data/index_lifecycle_management/${getPolicyEditPath(ilm.policy!)}`,
|
||||
})}
|
||||
target="_blank"
|
||||
>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
|
||||
import type * as estypes from '@elastic/elasticsearch/lib/api/types';
|
||||
import type { estypes } from '@elastic/elasticsearch';
|
||||
|
||||
import fakeDeprecations from '../__fixtures__/fake_deprecations.json';
|
||||
import * as healthIndicatorsMock from '../__fixtures__/health_indicators';
|
||||
|
@ -126,7 +126,6 @@ describe('getESUpgradeStatus', () => {
|
|||
],
|
||||
},
|
||||
data_streams: {},
|
||||
// @ts-expect-error not in types yet
|
||||
ilm_policies: {},
|
||||
templates: {},
|
||||
});
|
||||
|
@ -148,7 +147,7 @@ describe('getESUpgradeStatus', () => {
|
|||
...esMigrationsMock.getMockEsDeprecations(),
|
||||
...esMigrationsMock.getMockMlSettingsDeprecations(),
|
||||
};
|
||||
// @ts-ignore missing property definitions in ES resolve_during_rolling_upgrade and _meta
|
||||
// @ts-expect-error missing property definitions in ES resolve_during_rolling_upgrade and _meta
|
||||
esClient.migration.deprecations.mockResponse(mockResponse);
|
||||
|
||||
const enabledUpgradeStatus = await getESUpgradeStatus(esClient, {
|
||||
|
@ -217,7 +216,6 @@ describe('getESUpgradeStatus', () => {
|
|||
message: 'Index created before 7.0',
|
||||
url: 'https: //www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html',
|
||||
details: 'This index was created using version: 6.8.13',
|
||||
// @ts-ignore
|
||||
resolve_during_rolling_upgrade: false,
|
||||
_meta: {
|
||||
reindex_required: true,
|
||||
|
@ -228,7 +226,6 @@ describe('getESUpgradeStatus', () => {
|
|||
message: 'Index created before 7.0',
|
||||
url: 'https: //www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html',
|
||||
details: 'This index was created using version: 6.8.13',
|
||||
// @ts-ignore
|
||||
resolve_during_rolling_upgrade: false,
|
||||
_meta: {
|
||||
reindex_required: true,
|
||||
|
@ -238,7 +235,6 @@ describe('getESUpgradeStatus', () => {
|
|||
ml_settings: [],
|
||||
index_settings: {},
|
||||
data_streams: {},
|
||||
// @ts-expect-error not in types yet
|
||||
ilm_policies: {},
|
||||
templates: {},
|
||||
});
|
||||
|
@ -313,7 +309,6 @@ describe('getESUpgradeStatus', () => {
|
|||
},
|
||||
],
|
||||
},
|
||||
// @ts-expect-error not in types yet
|
||||
ilm_policies: {},
|
||||
templates: {},
|
||||
});
|
||||
|
@ -369,7 +364,6 @@ describe('getESUpgradeStatus', () => {
|
|||
],
|
||||
},
|
||||
data_streams: {},
|
||||
// @ts-expect-error not in types yet
|
||||
ilm_policies: {},
|
||||
templates: {},
|
||||
});
|
||||
|
@ -398,7 +392,6 @@ describe('getESUpgradeStatus', () => {
|
|||
message: 'Index created before 7.0',
|
||||
url: 'https: //www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html',
|
||||
details: 'This index was created using version: 6.8.13',
|
||||
// @ts-ignore
|
||||
resolve_during_rolling_upgrade: false,
|
||||
_meta: {
|
||||
reindex_required: true,
|
||||
|
@ -408,7 +401,6 @@ describe('getESUpgradeStatus', () => {
|
|||
ml_settings: [],
|
||||
index_settings: {},
|
||||
data_streams: {},
|
||||
// @ts-expect-error not in types yet
|
||||
ilm_policies: {},
|
||||
templates: {},
|
||||
});
|
||||
|
@ -417,7 +409,7 @@ describe('getESUpgradeStatus', () => {
|
|||
cluster_name: 'mock',
|
||||
indicators: {
|
||||
disk: healthIndicatorsMock.diskIndicatorGreen,
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
shards_capacity: healthIndicatorsMock.shardCapacityIndicatorRed,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -324,7 +324,7 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio
|
|||
const connectorId = outcomeAndMessage?.kibana?.action?.id ?? '';
|
||||
const timedOut = (bucket?.timeoutMessage?.doc_count ?? 0) > 0;
|
||||
return {
|
||||
id: bucket?.key ?? '',
|
||||
id: bucket?.key ? `${bucket.key}` : '',
|
||||
timestamp: bucket?.actionExecution?.executeStartTime.value_as_string ?? '',
|
||||
duration_ms: durationUs / Millis2Nanos,
|
||||
status,
|
||||
|
|
|
@ -530,7 +530,7 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio
|
|||
? outcomeMessageAndMaintenanceWindow.rule?.name ?? ''
|
||||
: '';
|
||||
return {
|
||||
id: bucket?.key ?? '',
|
||||
id: bucket?.key ? `${bucket.key}` : '', // `key` can be a number, this way we stringify it.
|
||||
timestamp: bucket?.ruleExecution?.executeStartTime.value_as_string ?? '',
|
||||
duration_ms: durationUs / Millis2Nanos,
|
||||
status,
|
||||
|
|
|
@ -101,7 +101,7 @@ export const findGapsSearchAfter = async ({
|
|||
return {
|
||||
total: gapsResponse.total,
|
||||
data: transformToGap(gapsResponse),
|
||||
searchAfter: gapsResponse.search_after,
|
||||
searchAfter: gapsResponse.search_after as SortResults[] | undefined,
|
||||
pitId: gapsResponse.pit_id,
|
||||
};
|
||||
} catch (err) {
|
||||
|
|
|
@ -253,7 +253,7 @@ function getWrappedEqlSearchFn(opts: WrapEsClientOpts) {
|
|||
requestTimeout ? ` and ${requestTimeout}ms requestTimeout` : ''
|
||||
}`
|
||||
);
|
||||
const result = (await originalEqlSearch.call(opts.esClient, params, {
|
||||
const result = (await originalEqlSearch.call(opts.esClient.eql, params, {
|
||||
...searchOptions,
|
||||
...(requestTimeout
|
||||
? {
|
||||
|
|
|
@ -340,7 +340,7 @@ export function parseRuleTypeBucket(
|
|||
alertsPercentilesByType: { p50: {}, p90: {}, p99: {} },
|
||||
};
|
||||
for (const bucket of buckets ?? []) {
|
||||
const ruleType: string = replaceDotSymbols(bucket?.key) ?? '';
|
||||
const ruleType: string = replaceDotSymbols(`${bucket?.key ?? ''}`);
|
||||
const numExecutions: number = bucket?.doc_count ?? 0;
|
||||
const avgExecutionTimeNanos = bucket?.avg_execution_time?.value ?? 0;
|
||||
const avgEsSearchTimeMillis = bucket?.avg_es_search_duration?.value ?? 0;
|
||||
|
@ -391,7 +391,7 @@ export function parseExecutionFailureByRuleType(
|
|||
const executionFailuresWithRuleTypeBuckets: FlattenedExecutionFailureBucket[] = flatMap(
|
||||
buckets ?? [],
|
||||
(bucket) => {
|
||||
const ruleType: string = replaceDotSymbols(bucket.key);
|
||||
const ruleType: string = replaceDotSymbols(`${bucket.key}`);
|
||||
|
||||
/**
|
||||
* Execution failure bucket format
|
||||
|
@ -409,7 +409,7 @@ export function parseExecutionFailureByRuleType(
|
|||
|
||||
const executionFailuresBuckets = bucket?.execution_failures?.by_reason
|
||||
?.buckets as AggregationsStringTermsBucketKeys[];
|
||||
return (executionFailuresBuckets ?? []).map((b) => ({ ...b, ruleType }));
|
||||
return (executionFailuresBuckets ?? []).map((b) => ({ ...b, key: `${b.key}`, ruleType }));
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -548,7 +548,7 @@ export function parseExecutionCountAggregationResults(results: {
|
|||
countTotalFailedExecutions: results?.execution_failures?.doc_count ?? 0,
|
||||
countFailedExecutionsByReason: executionFailuresByReasonBuckets.reduce<Record<string, number>>(
|
||||
(acc, bucket: AggregationsStringTermsBucketKeys) => {
|
||||
const reason: string = bucket.key;
|
||||
const reason: string = `${bucket.key}`;
|
||||
acc[reason] = bucket.doc_count ?? 0;
|
||||
return acc;
|
||||
},
|
||||
|
|
|
@ -163,12 +163,14 @@ export function parseBucket(
|
|||
> {
|
||||
return (buckets ?? []).reduce(
|
||||
(summary, bucket) => {
|
||||
const status: string = bucket.key;
|
||||
const status: string = `${bucket.key}`;
|
||||
const taskTypeBuckets = bucket?.by_task_type?.buckets as AggregationsStringTermsBucketKeys[];
|
||||
|
||||
const byTaskType = (taskTypeBuckets ?? []).reduce<Record<string, number>>(
|
||||
(acc, taskTypeBucket: AggregationsStringTermsBucketKeys) => {
|
||||
const taskType: string = replaceDotSymbols(taskTypeBucket.key.replace('alerting:', ''));
|
||||
const taskType: string = replaceDotSymbols(
|
||||
`${taskTypeBucket.key}`.replace('alerting:', '')
|
||||
);
|
||||
acc[taskType] = taskTypeBucket.doc_count ?? 0;
|
||||
return acc;
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ export function parseSimpleRuleTypeBucket(
|
|||
) {
|
||||
const buckets = ruleTypeBuckets as AggregationsStringTermsBucketKeys[];
|
||||
return (buckets ?? []).reduce((acc, bucket: AggregationsStringTermsBucketKeys) => {
|
||||
const ruleType: string = replaceDotSymbols(bucket.key);
|
||||
const ruleType: string = replaceDotSymbols(`${bucket.key}`);
|
||||
acc[ruleType] = bucket.doc_count ?? 0;
|
||||
return acc;
|
||||
}, {} as Record<string, number>);
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { QueryDslBoolQuery } from '@elastic/elasticsearch/lib/api/types';
|
||||
import type {
|
||||
AggregationsCompositeAggregateKey,
|
||||
QueryDslBoolQuery,
|
||||
} from '@elastic/elasticsearch/lib/api/types';
|
||||
import type { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { extractIndexNameFromBackingIndex } from '../../../common/utils';
|
||||
import { DataStreamDocsStat } from '../../../common/api_types';
|
||||
import { createDatasetQualityESClient } from '../../utils';
|
||||
import { rangeQuery } from '../../utils/queries';
|
||||
|
||||
interface Dataset {
|
||||
interface Dataset extends AggregationsCompositeAggregateKey {
|
||||
dataset: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -935,7 +935,7 @@ export function getQueryBodyWithAuthFilter(
|
|||
};
|
||||
}
|
||||
|
||||
function getNamespaceQuery(namespace?: string) {
|
||||
function getNamespaceQuery(namespace?: string): estypes.QueryDslQueryContainer {
|
||||
const defaultNamespaceQuery = {
|
||||
bool: {
|
||||
must_not: {
|
||||
|
@ -948,7 +948,7 @@ function getNamespaceQuery(namespace?: string) {
|
|||
const namedNamespaceQuery = {
|
||||
term: {
|
||||
'kibana.saved_objects.namespace': {
|
||||
value: namespace,
|
||||
value: namespace!,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -175,7 +175,9 @@ export const generateEsApiResponseMock = <TBody extends Record<string, any>>(
|
|||
body: undefined,
|
||||
querystring: '',
|
||||
},
|
||||
options: {},
|
||||
options: {
|
||||
requestTimeout: 30_000,
|
||||
},
|
||||
id: 7160,
|
||||
},
|
||||
name: 'elasticsearch-js',
|
||||
|
|
|
@ -96,8 +96,7 @@ async function handleMlModelInstall({
|
|||
{
|
||||
model_id: mlModel.installationName,
|
||||
defer_definition_decompression: true,
|
||||
// @ts-expect-error timeout is not declared
|
||||
timeout: '45s',
|
||||
querystring: { timeout: '45s' },
|
||||
body: mlModel.content,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -221,7 +221,7 @@ export async function handleExperimentalDatastreamFeatureOptIn({
|
|||
|
||||
await esClient.indices.putIndexTemplate({
|
||||
name: featureMapEntry.data_stream,
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error elasticsearch@9.0.0 https://github.com/elastic/elasticsearch-js/issues/2584
|
||||
body: indexTemplateBody,
|
||||
_meta: {
|
||||
has_experimental_data_stream_indexing_features: featureMapEntry.features.tsdb,
|
||||
|
|
|
@ -55,9 +55,7 @@ export function registerPutDataRetention({ router, lib: { handleEsError } }: Rou
|
|||
const { headers } = await client.asCurrentUser.indices.putDataLifecycle(
|
||||
{
|
||||
name: dataStreams,
|
||||
lifecycle: {
|
||||
data_retention: dataRetention,
|
||||
},
|
||||
data_retention: dataRetention,
|
||||
},
|
||||
{ meta: true }
|
||||
);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { uniq } from 'lodash';
|
||||
import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server';
|
||||
import { AGENTS_INDEX, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
|
||||
import type { SortResults } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { OSQUERY_INTEGRATION_NAME } from '../../common';
|
||||
import type { OsqueryAppContext } from './osquery_app_context_services';
|
||||
|
||||
|
@ -24,9 +25,9 @@ export const aggregateResults = async (
|
|||
generator: (
|
||||
page: number,
|
||||
perPage: number,
|
||||
searchAfter?: unknown[],
|
||||
searchAfter?: SortResults,
|
||||
pitId?: string
|
||||
) => Promise<{ results: string[]; total: number; searchAfter?: unknown[] }>,
|
||||
) => Promise<{ results: string[]; total: number; searchAfter?: SortResults }>,
|
||||
esClient: ElasticsearchClient,
|
||||
context: OsqueryAppContext
|
||||
) => {
|
||||
|
@ -41,7 +42,7 @@ export const aggregateResults = async (
|
|||
index: AGENTS_INDEX,
|
||||
keep_alive: '10m',
|
||||
});
|
||||
let currentSort: unknown[] | undefined;
|
||||
let currentSort: SortResults | undefined;
|
||||
// Refetch first page with PIT
|
||||
const { results: pitInitialResults, searchAfter } = await generator(
|
||||
1,
|
||||
|
@ -111,7 +112,7 @@ export const parseAgentSelection = async (
|
|||
if (allAgentsSelected) {
|
||||
const kuery = kueryFragments.join(' and ');
|
||||
const fetchedAgents = await aggregateResults(
|
||||
async (page, perPage, searchAfter?: unknown[], pitId?: string) => {
|
||||
async (page, perPage, searchAfter?: SortResults, pitId?: string) => {
|
||||
const res = await agentService.listAgents({
|
||||
...(searchAfter ? { searchAfter } : {}),
|
||||
...(pitId ? { pitId } : {}),
|
||||
|
@ -145,7 +146,7 @@ export const parseAgentSelection = async (
|
|||
kueryFragments.push(`(${groupFragments.join(' or ')})`);
|
||||
const kuery = kueryFragments.join(' and ');
|
||||
const fetchedAgents = await aggregateResults(
|
||||
async (page, perPage, searchAfter?: unknown[], pitId?: string) => {
|
||||
async (page, perPage, searchAfter?: SortResults, pitId?: string) => {
|
||||
const res = await agentService.listAgents({
|
||||
...(searchAfter ? { searchAfter } : {}),
|
||||
...(pitId ? { pitId } : {}),
|
||||
|
|
|
@ -520,7 +520,7 @@ export class AlertsClient {
|
|||
query: object | string;
|
||||
operation: WriteOperations.Update | ReadOperations.Find | ReadOperations.Get;
|
||||
}) {
|
||||
let lastSortIds;
|
||||
let lastSortIds: Array<string | number> | undefined;
|
||||
let hasSortIds = true;
|
||||
const alertSpaceId = this.spaceId;
|
||||
if (alertSpaceId == null) {
|
||||
|
|
|
@ -595,10 +595,10 @@ export const categorizeAggregations = (aggregationResponse?: ApiKeyAggregations)
|
|||
: [];
|
||||
|
||||
typeBuckets.forEach((type) => {
|
||||
typeFilters.push(type.key);
|
||||
typeFilters.push(type.key as CategorizedApiKey['type']);
|
||||
});
|
||||
usernameBuckets.forEach((username) => {
|
||||
usernameFilters.push(username.key);
|
||||
usernameFilters.push(`${username.key}`);
|
||||
});
|
||||
const { namePrefixBased, metadataBased } = managed?.buckets || {};
|
||||
if (
|
||||
|
|
|
@ -1580,7 +1580,7 @@ describe('Session index', () => {
|
|||
index: aliasName,
|
||||
document: sessionValue,
|
||||
refresh: false,
|
||||
require_alias: true,
|
||||
querystring: { require_alias: true },
|
||||
},
|
||||
{ ignore: [404], meta: true }
|
||||
);
|
||||
|
@ -1591,7 +1591,7 @@ describe('Session index', () => {
|
|||
index: aliasName,
|
||||
document: sessionValue,
|
||||
refresh: false,
|
||||
require_alias: true,
|
||||
querystring: { require_alias: true },
|
||||
},
|
||||
{ ignore: [], meta: true }
|
||||
);
|
||||
|
@ -1635,7 +1635,7 @@ describe('Session index', () => {
|
|||
index: aliasName,
|
||||
document: sessionValue,
|
||||
refresh: false,
|
||||
require_alias: true,
|
||||
querystring: { require_alias: true },
|
||||
},
|
||||
{ meta: true, ignore: [404] }
|
||||
);
|
||||
|
|
|
@ -10,7 +10,6 @@ import type {
|
|||
AggregateName,
|
||||
AggregationsMultiTermsAggregate,
|
||||
BulkOperationContainer,
|
||||
CreateRequest,
|
||||
IndicesCreateRequest,
|
||||
MsearchRequestItem,
|
||||
SearchHit,
|
||||
|
@ -786,8 +785,8 @@ export class SessionIndex {
|
|||
index: this.aliasName,
|
||||
document: sessionValueToStore,
|
||||
refresh: false,
|
||||
require_alias: true,
|
||||
} as CreateRequest,
|
||||
querystring: { require_alias: true },
|
||||
},
|
||||
{ meta: true, ignore: ignore404 ? [404] : [] }
|
||||
);
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@ export async function executor(core: CoreSetup, options: ExecutorOptions<EsQuery
|
|||
if (!isGroupAgg) {
|
||||
// update the timestamp based on the current search results
|
||||
const firstValidTimefieldSort = getValidTimefieldSort(
|
||||
// @ts-expect-error `sort` now depends on `FieldValue` that is too broad
|
||||
result.hits.find((hit) => getValidTimefieldSort(hit.sort))?.sort
|
||||
);
|
||||
if (firstValidTimefieldSort) {
|
||||
|
|
|
@ -116,12 +116,12 @@ describe('InferenceConnector', () => {
|
|||
rerank: [
|
||||
{
|
||||
index: 2,
|
||||
score: 0.011597361,
|
||||
relevance_score: 0.011597361,
|
||||
text: 'leia',
|
||||
},
|
||||
{
|
||||
index: 0,
|
||||
score: 0.006338922,
|
||||
relevance_score: 0.006338922,
|
||||
text: 'luke',
|
||||
},
|
||||
],
|
||||
|
@ -165,7 +165,9 @@ describe('InferenceConnector', () => {
|
|||
},
|
||||
{ asStream: false }
|
||||
);
|
||||
expect(response).toEqual(mockResponseRerank.rerank);
|
||||
expect(response).toEqual(
|
||||
mockResponseRerank.rerank.map(({ relevance_score: score, ...rest }) => ({ ...rest, score }))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ export class InferenceConnector extends SubActionConnector<Config, Secrets> {
|
|||
false,
|
||||
signal
|
||||
);
|
||||
return response.rerank!;
|
||||
return response.rerank!.map(({ relevance_score: score, ...rest }) => ({ score, ...rest }));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,9 +112,7 @@ export async function updateDataStreamsLifecycle({
|
|||
() =>
|
||||
esClient.indices.putDataLifecycle({
|
||||
name: names,
|
||||
lifecycle: {
|
||||
data_retention: isDslLifecycle(lifecycle) ? lifecycle.dsl.data_retention : undefined,
|
||||
},
|
||||
data_retention: isDslLifecycle(lifecycle) ? lifecycle.dsl.data_retention : undefined,
|
||||
}),
|
||||
{ logger }
|
||||
);
|
||||
|
|
|
@ -157,6 +157,7 @@ export class TaskManagerMetricsCollector implements ITaskEventEmitter<TaskLifecy
|
|||
}) ?? {};
|
||||
const byTaskType = ((aggregations.byTaskType.buckets as OverdueTaskAggBucket[]) ?? []).reduce(
|
||||
(acc: Record<string, number>, bucket: OverdueTaskAggBucket) => {
|
||||
// @ts-expect-error there's no way that buckets (array) matches `number`
|
||||
acc[bucket.key] = bucket?.overdueByHistogram?.buckets ?? [];
|
||||
return acc;
|
||||
},
|
||||
|
|
|
@ -78,7 +78,7 @@ export class TaskOverdueMetricsAggregator implements ITaskMetricsAggregator<Task
|
|||
for (const key of Object.keys(metric.numOverdueTasks)) {
|
||||
const hist = new SimpleHistogram(HDR_HISTOGRAM_MAX, HDR_HISTOGRAM_BUCKET_SIZE);
|
||||
(metric.numOverdueTasks[key] ?? []).forEach((bucket) => {
|
||||
const overdueInSec = parseInt(bucket.key, 10);
|
||||
const overdueInSec = parseInt(`${bucket.key}`, 10);
|
||||
hist.record(overdueInSec, bucket.doc_count);
|
||||
|
||||
if (key === 'total') {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
|
||||
import type { FieldValue, QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
|
||||
import type { SearchFilter } from './generate_search_schema';
|
||||
|
||||
export const createFilterClauses = ({
|
||||
|
@ -22,7 +22,7 @@ export const createFilterClauses = ({
|
|||
if (filter) {
|
||||
if (filter.type === 'keyword' || filter.type === 'boolean') {
|
||||
clauses.push({
|
||||
term: { [field]: value },
|
||||
term: { [field]: value as FieldValue },
|
||||
});
|
||||
}
|
||||
// TODO: handle other field types, date mostly
|
||||
|
|
|
@ -24,6 +24,7 @@ export type ApmAlertsRequiredParams = ESSearchRequest & {
|
|||
query?: estypes.QueryDslQueryContainer;
|
||||
sort?: estypes.SortOptions[];
|
||||
_source?: string[] | false;
|
||||
search_after?: Array<string | number>;
|
||||
};
|
||||
|
||||
export async function getApmAlertsClient({
|
||||
|
|
|
@ -18,6 +18,7 @@ type RequiredParams = ESSearchRequest & {
|
|||
track_total_hits: boolean | number;
|
||||
sort?: estypes.SortOptions[];
|
||||
_source?: string[] | false;
|
||||
search_after?: Array<string | number>;
|
||||
};
|
||||
|
||||
export type InfraAlertsClient = Awaited<ReturnType<typeof getInfraAlertsClient>>;
|
||||
|
|
|
@ -30,6 +30,7 @@ export async function createAlertsClient({
|
|||
sort?: SortOptions[];
|
||||
size: number;
|
||||
track_total_hits: boolean | number;
|
||||
search_after?: Array<string | number>;
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -32,6 +32,7 @@ export async function getAlertsClient({
|
|||
track_total_hits: boolean | number;
|
||||
sort?: estypes.SortOptions[];
|
||||
_source?: string[] | false;
|
||||
search_after?: Array<string | number>;
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -56,7 +56,7 @@ export function termsQuery(
|
|||
field: string,
|
||||
...values: Array<string | boolean | undefined | number | null>
|
||||
): QueryDslQueryContainer[] {
|
||||
const filtered = reject(values, isUndefinedOrNull);
|
||||
const filtered = reject(values, isUndefinedOrNull) as Array<NonNullable<(typeof values)[number]>>;
|
||||
|
||||
if (!filtered.length) {
|
||||
return [];
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { timeslicesBudgetingMethodSchema } from '@kbn/slo-schema';
|
||||
import type { AggregationsCompositeAggregateKey } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { Duration, SLODefinition, toDurationUnit } from '../../../../domain/models';
|
||||
import { getDelayInSecondsFromSLO } from '../../../../domain/services/get_delay_in_seconds_from_slo';
|
||||
import { getLookbackDateRange } from '../../../../domain/services/get_lookback_date_range';
|
||||
|
@ -17,7 +18,7 @@ type BurnRateWindowWithDuration = WindowSchema & {
|
|||
shortDuration: Duration;
|
||||
};
|
||||
|
||||
export interface EvaluationAfterKey {
|
||||
export interface EvaluationAfterKey extends AggregationsCompositeAggregateKey {
|
||||
instanceId: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
*/
|
||||
|
||||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
import type { AggregationsCompositeAggregateKey } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
SUMMARY_DESTINATION_INDEX_PATTERN,
|
||||
SUMMARY_TEMP_INDEX_NAME,
|
||||
} from '../../../common/constants';
|
||||
|
||||
interface AggBucketKey {
|
||||
interface AggBucketKey extends AggregationsCompositeAggregateKey {
|
||||
spaceId: string;
|
||||
id: string;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,11 @@ export class DefaultSummarySearchClient implements SummarySearchClient {
|
|||
const finalTotal = total - (tempSummaryDocuments.length - tempSummaryDocumentsDeduped.length);
|
||||
|
||||
const paginationResults = isCursorPagination(pagination)
|
||||
? { searchAfter: finalResults[finalResults.length - 1].sort, size: pagination.size }
|
||||
? {
|
||||
// `sort` has unknown as types
|
||||
searchAfter: finalResults[finalResults.length - 1].sort as Array<string | number>,
|
||||
size: pagination.size,
|
||||
}
|
||||
: pagination;
|
||||
|
||||
return {
|
||||
|
|
|
@ -56,7 +56,7 @@ export function termsQuery(
|
|||
field: string,
|
||||
...values: Array<string | boolean | undefined | number | null>
|
||||
): QueryDslQueryContainer[] {
|
||||
const filtered = reject(values, isUndefinedOrNull);
|
||||
const filtered = reject(values, isUndefinedOrNull) as Array<NonNullable<(typeof values)[number]>>;
|
||||
|
||||
if (!filtered.length) {
|
||||
return [];
|
||||
|
|
|
@ -221,12 +221,14 @@ export const searchFindingsHandler = (findings: CspFinding[]) =>
|
|||
const hasRuleSectionQuerySearchTerm =
|
||||
isArray(filter) &&
|
||||
isArray(filter[0]?.bool?.should) &&
|
||||
// @ts-expect-error FieldValue is now very broad (can be anything)
|
||||
filter[0]?.bool?.should?.[0]?.term?.['rule.section']?.value !== undefined;
|
||||
|
||||
if (hasRuleSectionQuerySearchTerm) {
|
||||
const filteredFindings = findings.filter((finding) => {
|
||||
const termValue = (filter[0].bool?.should as estypes.QueryDslQueryContainer[])?.[0]?.term?.[
|
||||
'rule.section'
|
||||
// @ts-expect-error FieldValue is now very broad (can be anything)
|
||||
]?.value;
|
||||
return finding.rule.section === termValue;
|
||||
});
|
||||
|
|
|
@ -379,7 +379,7 @@ const getAccountStatsBasedOnEnablesRule = async (
|
|||
must_not: mutedRulesFilterQuery,
|
||||
must: {
|
||||
terms: {
|
||||
'rule.benchmark.id': benchmarksWithMutedRules,
|
||||
'rule.benchmark.id': benchmarksWithMutedRules as string[],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -315,7 +315,7 @@ export const formatAggExecutionEventFromBucket = (
|
|||
const backfill = getBackfill(bucket);
|
||||
|
||||
return {
|
||||
execution_uuid: bucket?.key ?? '',
|
||||
execution_uuid: bucket?.key ? `${bucket.key}` : '',
|
||||
timestamp: bucket?.ruleExecution?.executeStartTime.value_as_string ?? '',
|
||||
duration_ms: durationUs / ONE_MILLISECOND_AS_NANOSECONDS,
|
||||
status: bucket?.ruleExecution?.outcomeAndMessage?.hits?.hits[0]?._source?.event?.outcome,
|
||||
|
|
|
@ -276,7 +276,7 @@ export const createThreatSignals = async ({
|
|||
// this could happen when event has empty sort field
|
||||
// https://github.com/elastic/kibana/issues/174573 (happens to IM rule only since it uses desc order for events search)
|
||||
// when negative sort id used in subsequent request it fails, so when negative sort value found we don't do next request
|
||||
const hasNegativeDateSort = sortIds?.some((val) => val < 0);
|
||||
const hasNegativeDateSort = sortIds?.some((val) => Number(val) < 0);
|
||||
|
||||
if (hasNegativeDateSort) {
|
||||
ruleExecutionLogger.debug(
|
||||
|
|
|
@ -203,7 +203,7 @@ export const searchAfterAndBulkCreateFactory = async ({
|
|||
// this could happen when event has empty sort field
|
||||
// https://github.com/elastic/kibana/issues/174573 (happens to IM rule only since it uses desc order for events search)
|
||||
// when negative sort id used in subsequent request it fails, so when negative sort value found we don't do next request
|
||||
const hasNegativeNumber = lastSortIds?.some((val) => val < 0);
|
||||
const hasNegativeNumber = lastSortIds?.some((val) => Number(val) < 0);
|
||||
if (lastSortIds != null && lastSortIds.length !== 0 && !hasNegativeNumber) {
|
||||
sortIds = lastSortIds;
|
||||
} else {
|
||||
|
|
|
@ -709,7 +709,7 @@ export const getSafeSortIds = (sortIds: estypes.SortResults | undefined) => {
|
|||
return sortIds?.map((sortId) => {
|
||||
// haven't determined when we would receive a null value for a sort id
|
||||
// but in case we do, default to sending the stringified Java max_int
|
||||
if (sortId == null || sortId === '' || sortId >= Number.MAX_SAFE_INTEGER) {
|
||||
if (sortId == null || sortId === '' || Number(sortId) >= Number.MAX_SAFE_INTEGER) {
|
||||
return '9223372036854775807';
|
||||
}
|
||||
return sortId;
|
||||
|
|
|
@ -318,13 +318,15 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
|
|||
const migrationsAgg = result.aggregations?.migrationIds as AggregationsStringTermsAggregate;
|
||||
const buckets = (migrationsAgg?.buckets as AggregationsStringTermsBucket[]) ?? [];
|
||||
return buckets.map((bucket) => ({
|
||||
id: bucket.key,
|
||||
id: `${bucket.key}`,
|
||||
rules: {
|
||||
total: bucket.doc_count,
|
||||
...this.statusAggCounts(bucket.status),
|
||||
...this.statusAggCounts(bucket.status as AggregationsStringTermsAggregate),
|
||||
},
|
||||
created_at: bucket.createdAt?.value_as_string,
|
||||
last_updated_at: bucket.lastUpdatedAt?.value_as_string,
|
||||
created_at: (bucket.createdAt as AggregationsMinAggregate | undefined)
|
||||
?.value_as_string as string,
|
||||
last_updated_at: (bucket.lastUpdatedAt as AggregationsMaxAggregate | undefined)
|
||||
?.value_as_string as string,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -139,11 +139,7 @@ export default function ({ getService }) {
|
|||
};
|
||||
|
||||
const { body } = await createJob(payload);
|
||||
// expect(body.message).to.contain('unknown field [invalid]');
|
||||
// elasticsearch@9.0.0 https://github.com/elastic/elasticsearch-js/issues/2584
|
||||
// At the moment, the client places unknown fields as URL parameters, we are discussing changing that to use the body as a catch-all.
|
||||
// This might revert the asssertion to the above.
|
||||
expect(body.message).to.contain('contains unrecognized parameter: [invalid]');
|
||||
expect(body.message).to.contain('unknown field [invalid]');
|
||||
});
|
||||
|
||||
it('should list the newly created job', async () => {
|
||||
|
|
|
@ -2139,10 +2139,10 @@
|
|||
"@elastic/transport" "^8.3.1"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@elastic/elasticsearch@9.0.0-alpha.3":
|
||||
version "9.0.0-alpha.3"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-9.0.0-alpha.3.tgz#7580ca3f984cef7c4a9ecda0c5853dfa4671996d"
|
||||
integrity sha512-10ZJtFXij0TiDc+5WpDfHB+ckEeeEgo6ZwY4QjjNNEFSLZSx+gg7DBgQkddRYpjBe7VM6dBhY76NkRmgod7p9A==
|
||||
"@elastic/elasticsearch@9.0.0-alpha.4":
|
||||
version "9.0.0-alpha.4"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-9.0.0-alpha.4.tgz#747541e0bd93d2310d522c7d6bf21bec5872eacd"
|
||||
integrity sha512-qGtiC3lWH//J4rTneaXU8vPpxQe8kPO57ZU94kMSttpyyDE+yvs0uh/tsOwKwQS9i5L37fGZG1I02x0Kf5HHfw==
|
||||
dependencies:
|
||||
"@elastic/transport" "9.0.0-alpha.1"
|
||||
apache-arrow "^18.0.0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue