[ResponseOps][MaintenanceWindow] Public maintenance window API (#216756)

Closes #198685

## Summary

This PR creates a public Maintenance Window API.

The work was done on a feature branch over multiple separate PRs. Here
we will merge the feature branch into `main`.
- https://github.com/elastic/kibana/pull/209734
- https://github.com/elastic/kibana/pull/213694
- https://github.com/elastic/kibana/pull/214747
- https://github.com/elastic/kibana/pull/213771

The [documentation PR](https://github.com/elastic/kibana/pull/212377)
still needs to be merged.

## Release Notes

Publish new public APIs for the Maintenance Window.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: lcawl <lcawley@elastic.co>
This commit is contained in:
Antonio 2025-04-16 11:39:38 +02:00 committed by GitHub
parent 334ca2ae50
commit 08d0717d46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
187 changed files with 3739 additions and 395 deletions

View file

@ -19,7 +19,8 @@ cmd="node scripts/capture_oas_snapshot \
--include-path /api/fleet \
--include-path /api/dashboards \
--include-path /api/saved_objects/_import \
--include-path /api/saved_objects/_export"
--include-path /api/saved_objects/_export \
--include-path /api/alerting/maintenance_window"
if is_pr && ! is_auto_commit_disabled; then
cmd="$cmd --update"
fi

View file

@ -4,7 +4,17 @@ info:
title: Overlays that are applicable to both serverless and non-serverless documentas
version: 0.0.1
actions:
# Add some tag descriptions and displayNames
# Add some tag descriptions and displayNames
- target: '$.tags[?(@.name=="maintenance-window")]'
description: Change tag description and displayName
update:
description: >
You can schedule single or recurring maintenance windows to temporarily reduce rule notifications.
For example, a maintenance window prevents false alarms during planned outages.
externalDocs:
description: Maintenance window documentation
url: https://www.elastic.co/docs/explore-analyze/alerts-cases/alerts/maintenance-windows
x-displayName: 'Maintenance windows'
- target: '$.tags[?(@.name=="alerting")]'
description: Change tag description and displayName
update:
@ -15,7 +25,7 @@ actions:
externalDocs:
description: Alerting documentation
url: https://www.elastic.co/docs/explore-analyze/alerts-cases/alerts
x-displayName: "Alerting"
x-displayName: 'Alerting'
- target: '$.tags[?(@.name=="cases")]'
description: Change tag description and displayName
update:
@ -26,7 +36,7 @@ actions:
externalDocs:
description: Cases documentation
url: https://www.elastic.co/docs/explore-analyze/alerts-cases/cases
x-displayName: "Cases"
x-displayName: 'Cases'
- target: '$.tags[?(@.name=="connectors")]'
description: Change tag description and displayName
update:
@ -36,28 +46,28 @@ actions:
externalDocs:
description: Connector documentation
url: https://www.elastic.co/docs/reference/kibana/connectors-kibana
x-displayName: "Connectors"
# Add some spaces API examples
x-displayName: 'Connectors'
# Add some spaces API examples
- target: "$.paths['/api/spaces/space']['post']"
description: "Add example to create space API"
description: 'Add example to create space API'
update:
requestBody:
content:
application/json:
examples:
createSpaceRequest:
$ref: "../examples/create_space_request.yaml"
$ref: '../examples/create_space_request.yaml'
- target: "$.paths['/api/spaces/space/{id}']['put']"
description: "Add example to update space API"
description: 'Add example to update space API'
update:
requestBody:
content:
application/json:
examples:
updateSpaceRequest:
$ref: "../examples/update_space_request.yaml"
$ref: '../examples/update_space_request.yaml'
- target: "$.paths['/api/spaces/space/{id}']['get']"
description: "Add example to get space API"
description: 'Add example to get space API'
update:
responses:
200:
@ -65,9 +75,9 @@ actions:
application/json:
examples:
getSpaceResponseExample:
$ref: "../examples/get_space_response.yaml"
$ref: '../examples/get_space_response.yaml'
- target: "$.paths['/api/spaces/space']['get']"
description: "Add example to get all spaces API"
description: 'Add example to get all spaces API'
update:
responses:
200:
@ -75,6 +85,6 @@ actions:
application/json:
examples:
getSpacesResponseExample1:
$ref: "../examples/get_spaces_response1.yaml"
$ref: '../examples/get_spaces_response1.yaml'
getSpacesResponseExample2:
$ref: "../examples/get_spaces_response2.yaml"
$ref: '../examples/get_spaces_response2.yaml'

View file

@ -209,6 +209,9 @@ export {
export const LEGACY_BASE_ALERT_API_PATH = '/api/alerts';
export const BASE_ALERTING_API_PATH = '/api/alerting';
export const BASE_MAINTENANCE_WINDOW_API_PATH = '/api/maintenance_window';
// Internal
export const INTERNAL_BASE_ALERTING_API_PATH = '/internal/alerting' as const;
export const INTERNAL_ALERTING_SNOOZE_RULE =
`${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_snooze` as const;
@ -242,6 +245,14 @@ export const INTERNAL_ALERTING_GAPS_GET_SUMMARY_BY_RULE_IDS_API_PATH =
export const INTERNAL_ALERTING_GAPS_FILL_BY_ID_API_PATH =
`${INTERNAL_ALERTING_GAPS_API_PATH}/_fill_by_id` as const;
// External
export const ARCHIVE_MAINTENANCE_WINDOW_API_PATH = `${BASE_MAINTENANCE_WINDOW_API_PATH}/{id}/_archive`;
export const UNARCHIVE_MAINTENANCE_WINDOW_API_PATH = `${BASE_MAINTENANCE_WINDOW_API_PATH}/{id}/_unarchive`;
export const CREATE_MAINTENANCE_WINDOW_API_PATH = BASE_MAINTENANCE_WINDOW_API_PATH;
export const GET_MAINTENANCE_WINDOW_API_PATH = `${BASE_MAINTENANCE_WINDOW_API_PATH}/{id}`;
export const UPDATE_MAINTENANCE_WINDOW_API_PATH = `${BASE_MAINTENANCE_WINDOW_API_PATH}/{id}`;
export const DELETE_MAINTENANCE_WINDOW_API_PATH = `${BASE_MAINTENANCE_WINDOW_API_PATH}/{id}`;
export const ALERTING_FEATURE_ID = 'alerts';
export const MONITORING_HISTORY_LIMIT = 200;
export const ENABLE_MAINTENANCE_WINDOWS = true;

View file

@ -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.
*/
export { archiveMaintenanceWindowRequestParamsSchema } from './schemas/latest';
export type {
ArchiveMaintenanceWindowRequestParams,
ArchiveMaintenanceWindowResponse,
} from './types/latest';
export { archiveMaintenanceWindowRequestParamsSchema as archiveMaintenanceWindowRequestParamsSchemaV1 } from './schemas/v1';
export type {
ArchiveMaintenanceWindowRequestParams as ArchiveMaintenanceWindowRequestParamsV1,
ArchiveMaintenanceWindowResponse as ArchiveMaintenanceWindowResponseV1,
} from './types/latest';

View file

@ -0,0 +1,8 @@
/*
* 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 { archiveMaintenanceWindowRequestParamsSchema } from './v1';

View file

@ -0,0 +1,16 @@
/*
* 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 { schema } from '@kbn/config-schema';
export const archiveMaintenanceWindowRequestParamsSchema = schema.object({
id: schema.string({
meta: {
description: 'The identifier for the maintenance window to be archived.',
},
}),
});

View file

@ -0,0 +1,8 @@
/*
* 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 type { ArchiveMaintenanceWindowRequestParams, ArchiveMaintenanceWindowResponse } from './v1';

View file

@ -0,0 +1,18 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';
import type { MaintenanceWindowResponseV1 } from '../../../response';
import type { archiveMaintenanceWindowRequestParamsSchemaV1 } from '..';
export type ArchiveMaintenanceWindowRequestParams = TypeOf<
typeof archiveMaintenanceWindowRequestParamsSchemaV1
>;
export interface ArchiveMaintenanceWindowResponse {
body: MaintenanceWindowResponseV1;
}

View file

@ -0,0 +1,18 @@
/*
* 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 { createMaintenanceWindowRequestBodySchema } from './schemas/latest';
export type {
CreateMaintenanceWindowRequestBody,
CreateMaintenanceWindowResponse,
} from './types/latest';
export { createMaintenanceWindowRequestBodySchema as createMaintenanceWindowRequestBodySchemaV1 } from './schemas/v1';
export type {
CreateMaintenanceWindowRequestBody as CreateMaintenanceWindowRequestBodyV1,
CreateMaintenanceWindowResponse as CreateMaintenanceWindowResponseV1,
} from './types/v1';

View file

@ -0,0 +1,8 @@
/*
* 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 { createMaintenanceWindowRequestBodySchema } from './v1';

View file

@ -0,0 +1,88 @@
/*
* 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 { createMaintenanceWindowRequestBodySchema } from './v1';
const maintenanceWindow = {
title: 'test-maintenance-window',
enabled: false,
schedule: {
custom: {
duration: '2h',
start: '2021-05-20T00:00:00.000Z',
recurring: {
every: '1d',
onWeekDay: ['TU', 'TH'],
onMonthDay: [1, 31],
onMonth: [1, 3, 5, 12],
end: '2021-05-20T00:00:00.000Z',
},
},
},
scope: {
alerting: {
query: {
kql: "_id: '1234'",
},
},
},
};
describe('createMaintenanceWindowRequestBodySchema', () => {
const mockCurrentDate = new Date('2021-05-05T00:00:00.000Z');
beforeEach(() => {
jest.clearAllMocks();
jest.useFakeTimers().setSystemTime(mockCurrentDate);
});
afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});
it('validates correctly with all fields', () => {
expect(createMaintenanceWindowRequestBodySchema.validate(maintenanceWindow))
.toMatchInlineSnapshot(`
Object {
"enabled": false,
"schedule": Object {
"custom": Object {
"duration": "2h",
"recurring": Object {
"end": "2021-05-20T00:00:00.000Z",
"every": "1d",
"onMonth": Array [
1,
3,
5,
12,
],
"onMonthDay": Array [
1,
31,
],
"onWeekDay": Array [
"TU",
"TH",
],
},
"start": "2021-05-20T00:00:00.000Z",
},
},
"scope": Object {
"alerting": Object {
"query": Object {
"kql": "_id: '1234'",
},
},
},
"title": "test-maintenance-window",
}
`);
});
});

View file

@ -0,0 +1,46 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { scheduleRequestSchemaV1 } from '../../../../../schedule';
export const createMaintenanceWindowRequestBodySchema = schema.object({
title: schema.string({
meta: {
description:
'The name of the maintenance window. While this name does not have to be unique, a distinctive name can help you identify a specific maintenance window.',
},
}),
enabled: schema.maybe(
schema.boolean({
meta: {
description:
'Whether the current maintenance window is enabled. Disabled maintenance windows do not suppress notifications.',
},
defaultValue: true,
})
),
schedule: schema.object({
custom: scheduleRequestSchemaV1,
}),
scope: schema.maybe(
schema.object({
// as we introduce more scopes, alerting will eventually become alerting: schema.maybe(schema.object({...
alerting: schema.object({
query: schema.object({
kql: schema.string({
meta: {
description:
'A filter written in Kibana Query Language (KQL). Only alerts matching this query will be supressed by the maintenance window.',
},
}),
}),
}),
})
),
});

View file

@ -0,0 +1,15 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';
import type { MaintenanceWindowResponseV1 } from '../../../response';
import type { createMaintenanceWindowRequestBodySchemaV1 } from '..';
export type CreateMaintenanceWindowRequestBody = TypeOf<
typeof createMaintenanceWindowRequestBodySchemaV1
>;
export type CreateMaintenanceWindowResponse = MaintenanceWindowResponseV1;

View file

@ -0,0 +1,16 @@
/*
* 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 { schema } from '@kbn/config-schema';
export const deleteParamsSchema = schema.object({
id: schema.string({
meta: {
description: 'The identifier for the maintenance window to be deleted.',
},
}),
});

View file

@ -0,0 +1,16 @@
/*
* 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 { schema } from '@kbn/config-schema';
export const getParamsSchema = schema.object({
id: schema.string({
meta: {
description: 'The identifier for the maintenance window.',
},
}),
});

View file

@ -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.
*/
import type { TypeOf } from '@kbn/config-schema';
import type { MaintenanceWindowResponseV1 } from '../../../response';
import type { getParamsSchemaV1 } from '..';
export type GetMaintenanceWindowRequestParams = TypeOf<typeof getParamsSchemaV1>;
export type GetMaintenanceWindowResponse = MaintenanceWindowResponseV1;

View file

@ -0,0 +1,26 @@
/*
* 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.
*/
/*
* Copyright Elasticseunarch B.V. and/or licensed to Elasticseunarch 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 { unarchiveMaintenanceWindowRequestParamsSchema } from './schemas/latest';
export type {
UnarchiveMaintenanceWindowRequestParams,
UnarchiveMaintenanceWindowResponse,
} from './types/latest';
export { unarchiveMaintenanceWindowRequestParamsSchema as unarchiveMaintenanceWindowRequestParamsSchemaV1 } from './schemas/v1';
export type {
UnarchiveMaintenanceWindowRequestParams as UnarchiveMaintenanceWindowRequestParamsV1,
UnarchiveMaintenanceWindowResponse as UnarchiveMaintenanceWindowResponseV1,
} from './types/latest';

View file

@ -0,0 +1,8 @@
/*
* 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 { unarchiveMaintenanceWindowRequestParamsSchema } from './v1';

View file

@ -0,0 +1,16 @@
/*
* 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 { schema } from '@kbn/config-schema';
export const unarchiveMaintenanceWindowRequestParamsSchema = schema.object({
id: schema.string({
meta: {
description: 'The identifier for the maintenance window to be unarchived.',
},
}),
});

View file

@ -0,0 +1,11 @@
/*
* 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 type {
UnarchiveMaintenanceWindowRequestParams,
UnarchiveMaintenanceWindowResponse,
} from './v1';

View file

@ -0,0 +1,18 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';
import type { MaintenanceWindowResponseV1 } from '../../../response';
import type { unarchiveMaintenanceWindowRequestParamsSchemaV1 } from '..';
export type UnarchiveMaintenanceWindowRequestParams = TypeOf<
typeof unarchiveMaintenanceWindowRequestParamsSchemaV1
>;
export interface UnarchiveMaintenanceWindowResponse {
body: MaintenanceWindowResponseV1;
}

View file

@ -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.
*/
export { updateMaintenanceWindowRequestBodySchema } from './schemas/latest';
export type {
UpdateMaintenanceWindowRequestBody,
UpdateMaintenanceWindowRequestParams,
UpdateMaintenanceWindowResponse,
} from './types/latest';
export {
updateMaintenanceWindowRequestBodySchema as updateMaintenanceWindowRequestBodySchemaV1,
updateMaintenanceWindowRequestParamsSchema as updateMaintenanceWindowRequestParamsSchemaV1,
} from './schemas/v1';
export type {
UpdateMaintenanceWindowRequestParams as UpdateMaintenanceWindowRequestParamsV1,
UpdateMaintenanceWindowRequestBody as UpdateMaintenanceWindowRequestBodyV1,
UpdateMaintenanceWindowResponse as UpdateMaintenanceWindowResponseV1,
} from './types/v1';

View file

@ -0,0 +1,9 @@
/*
* 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 { updateMaintenanceWindowRequestBodySchema } from './v1';
export { updateMaintenanceWindowRequestParamsSchema } from './v1';

View file

@ -0,0 +1,52 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { scheduleRequestSchemaV1 } from '../../../../../schedule';
export const updateMaintenanceWindowRequestBodySchema = schema.object({
title: schema.maybe(
schema.string({
meta: {
description:
'The name of the maintenance window. While this name does not have to be unique, a distinctive name can help you identify a specific maintenance window.',
},
})
),
enabled: schema.maybe(
schema.boolean({
meta: {
description:
'Whether the current maintenance window is enabled. Disabled maintenance windows do not suppress notifications.',
},
defaultValue: true,
})
),
schedule: schema.maybe(
schema.object({
custom: scheduleRequestSchemaV1,
})
),
scope: schema.maybe(
schema.object({
alerting: schema.object({
query: schema.object({
kql: schema.string({
meta: {
description:
'A filter written in Kibana Query Language (KQL). Only alerts matching this query will be supressed by the maintenance window.',
},
}),
}),
}),
})
),
});
export const updateMaintenanceWindowRequestParamsSchema = schema.object({
id: schema.string(),
});

View file

@ -0,0 +1,21 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';
import type { MaintenanceWindowResponseV1 } from '../../../response';
import type {
updateMaintenanceWindowRequestBodySchemaV1,
updateMaintenanceWindowRequestParamsSchemaV1,
} from '..';
export type UpdateMaintenanceWindowRequestParams = TypeOf<
typeof updateMaintenanceWindowRequestParamsSchemaV1
>;
export type UpdateMaintenanceWindowRequestBody = TypeOf<
typeof updateMaintenanceWindowRequestBodySchemaV1
>;
export type UpdateMaintenanceWindowResponse = MaintenanceWindowResponseV1;

View file

@ -0,0 +1,83 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { maintenanceWindowStatus as maintenanceWindowStatusV1 } from '../constants/v1';
import { scheduleResponseSchemaV1 } from '../../../../schedule';
export const maintenanceWindowResponseSchema = schema.object({
id: schema.string({
meta: {
description: 'The identifier for the maintenance window.',
},
}),
title: schema.string({
meta: {
description: 'The name of the maintenance window.',
},
}),
enabled: schema.boolean({
meta: {
description:
'Whether the current maintenance window is enabled. Disabled maintenance windows do not suppress notifications.',
},
}),
created_by: schema.nullable(
schema.string({
meta: {
description: 'The identifier for the user that created the maintenance window.',
},
})
),
updated_by: schema.nullable(
schema.string({
meta: {
description: 'The identifier for the user that last updated this maintenance window.',
},
})
),
created_at: schema.string({
meta: {
description: 'The date and time when the maintenance window was created.',
},
}),
updated_at: schema.string({
meta: {
description: 'The date and time when the maintenance window was last updated.',
},
}),
status: schema.oneOf(
[
schema.literal(maintenanceWindowStatusV1.RUNNING),
schema.literal(maintenanceWindowStatusV1.UPCOMING),
schema.literal(maintenanceWindowStatusV1.FINISHED),
schema.literal(maintenanceWindowStatusV1.ARCHIVED),
],
{
meta: {
description: 'The current status of the maintenance window.',
},
}
),
scope: schema.maybe(
schema.object({
alerting: schema.object({
query: schema.object({
kql: schema.string({
meta: { description: 'A filter written in Kibana Query Language (KQL).' },
}),
}),
}),
})
),
schedule: schema.object({
custom: scheduleResponseSchemaV1,
}),
});

View file

@ -6,9 +6,9 @@
*/
import { schema } from '@kbn/config-schema';
import { maintenanceWindowCategoryIdsSchemaV1 } from '../../../shared';
import { rRuleRequestSchemaV1 } from '../../../../r_rule';
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
import { maintenanceWindowCategoryIdsSchemaV1 } from '../../../../shared';
import { rRuleRequestSchemaV1 } from '../../../../../r_rule';
import { alertsFilterQuerySchemaV1 } from '../../../../../alerts_filter_query';
export const createBodySchema = schema.object({
title: schema.string(),

View file

@ -0,0 +1,8 @@
/*
* 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 type { CreateMaintenanceWindowRequestBody, CreateMaintenanceWindowResponse } from './v1';

View file

@ -0,0 +1,12 @@
/*
* 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 { deleteParamsSchema } from './schemas/latest';
export type { DeleteMaintenanceWindowRequestParams } from './types/latest';
export { deleteParamsSchema as deleteParamsSchemaV1 } from './schemas/v1';
export type { DeleteMaintenanceWindowRequestParams as DeleteMaintenanceWindowRequestParamsV1 } from './types/v1';

View file

@ -0,0 +1,8 @@
/*
* 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 type { DeleteMaintenanceWindowRequestParams } from './v1';

View file

@ -0,0 +1,11 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';
import type { deleteParamsSchemaV1 } from '..';
export type DeleteMaintenanceWindowRequestParams = TypeOf<typeof deleteParamsSchemaV1>;

View file

@ -0,0 +1,18 @@
/*
* 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 { getParamsSchema } from './schemas/latest';
export type {
GetMaintenanceWindowRequestParams,
GetMaintenanceWindowResponse,
} from './types/latest';
export { getParamsSchema as getParamsSchemaV1 } from './schemas/v1';
export type {
GetMaintenanceWindowRequestParams as GetMaintenanceWindowRequestParamsV1,
GetMaintenanceWindowResponse as GetMaintenanceWindowResponseV1,
} from './types/v1';

View file

@ -0,0 +1,8 @@
/*
* 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 { getParamsSchema } from './v1';

View file

@ -0,0 +1,8 @@
/*
* 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 type { GetMaintenanceWindowRequestParams, GetMaintenanceWindowResponse } from './v1';

View file

@ -7,6 +7,7 @@
import type { TypeOf } from '@kbn/config-schema';
import type { MaintenanceWindowResponseV1 } from '../../../response';
import type { getParamsSchemaV1 } from '..';
export type GetMaintenanceWindowRequestParams = TypeOf<typeof getParamsSchemaV1>;

View file

@ -6,9 +6,9 @@
*/
import { schema } from '@kbn/config-schema';
import { maintenanceWindowCategoryIdsSchemaV1 } from '../../../shared';
import { rRuleRequestSchemaV1 } from '../../../../r_rule';
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
import { maintenanceWindowCategoryIdsSchemaV1 } from '../../../../shared';
import { rRuleRequestSchemaV1 } from '../../../../../r_rule';
import { alertsFilterQuerySchemaV1 } from '../../../../../alerts_filter_query';
export const updateParamsSchema = schema.object({
id: schema.string(),

View file

@ -0,0 +1,12 @@
/*
* 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 type {
UpdateMaintenanceWindowRequestParams,
UpdateMaintenanceWindowRequestBody,
UpdateMaintenanceWindowResponse,
} from './v1';

View file

@ -0,0 +1,10 @@
/*
* 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 type { MaintenanceWindowStatus } from './v1';
export { maintenanceWindowStatus } from './v1';

View file

@ -0,0 +1,16 @@
/*
* 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 maintenanceWindowStatus = {
RUNNING: 'running',
UPCOMING: 'upcoming',
FINISHED: 'finished',
ARCHIVED: 'archived',
} as const;
export type MaintenanceWindowStatus =
(typeof maintenanceWindowStatus)[keyof typeof maintenanceWindowStatus];

View file

@ -0,0 +1,16 @@
/*
* 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 { maintenanceWindowResponseSchema } from './schemas/latest';
export { maintenanceWindowStatus } from './constants/latest';
export type { MaintenanceWindowStatus } from './constants/latest';
export type { MaintenanceWindowResponse } from './types/latest';
export { maintenanceWindowResponseSchema as maintenanceWindowResponseSchemaV1 } from './schemas/v1';
export { maintenanceWindowStatus as maintenanceWindowStatusV1 } from './constants/v1';
export type { MaintenanceWindowStatus as MaintenanceWindowStatusV1 } from './constants/v1';
export type { MaintenanceWindowResponse as MaintenanceWindowResponseV1 } from './types/v1';

View file

@ -7,9 +7,9 @@
import { schema } from '@kbn/config-schema';
import { maintenanceWindowStatus as maintenanceWindowStatusV1 } from '../constants/v1';
import { maintenanceWindowCategoryIdsSchemaV1 } from '../../shared';
import { rRuleResponseSchemaV1 } from '../../../r_rule';
import { alertsFilterQuerySchemaV1 } from '../../../alerts_filter_query';
import { maintenanceWindowCategoryIdsSchemaV1 } from '../../../shared';
import { rRuleResponseSchemaV1 } from '../../../../r_rule';
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
export const maintenanceWindowEventSchema = schema.object({
gte: schema.string(),

View file

@ -0,0 +1,11 @@
/*
* 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 type { TypeOf } from '@kbn/config-schema';
import type { maintenanceWindowResponseSchemaV1 } from '..';
export type MaintenanceWindowResponse = TypeOf<typeof maintenanceWindowResponseSchemaV1>;

View file

@ -5,12 +5,15 @@
* 2.0.
*/
export { scheduleRequestSchema } from './schema/latest';
export { scheduleRequestSchema, scheduleResponseSchema } from './schema/latest';
export { transformCustomScheduleToRRule } from './transforms/custom_to_rrule/latest';
export { transformRRuleToCustomSchedule } from './transforms/rrule_to_custom/latest';
export type { ScheduleRequest } from './types/latest';
export { scheduleRequestSchema as scheduleRequestSchemaV1 } from './schema/v1';
export {
scheduleRequestSchema as scheduleRequestSchemaV1,
scheduleResponseSchema as scheduleResponseSchemaV1,
} from './schema/v1';
export { transformCustomScheduleToRRule as transformCustomScheduleToRRuleV1 } from './transforms/custom_to_rrule/v1';
export { transformRRuleToCustomSchedule as transformRRuleToCustomScheduleV1 } from './transforms/rrule_to_custom/v1';
export type { ScheduleRequest as ScheduleRequestV1 } from './types/v1';

View file

@ -118,3 +118,76 @@ export const scheduleRequestSchema = schema.object(
validate: validateScheduleV1,
}
);
// The response schema has the same fields but without validation
export const scheduleResponseSchema = schema.object({
start: schema.string({
meta: {
description:
'The start date and time of the schedule, provided in ISO 8601 format and set to the UTC timezone. For example: `2025-03-12T12:00:00.000Z`.',
},
}),
duration: schema.string({
meta: {
description:
'The duration of the schedule. It allows values in `<integer><unit>` format. `<unit>` is one of `d`, `h`, `m`, or `s` for hours, minutes, seconds. For example: `1d`, `5h`, `30m`, `5000s`.',
},
}),
timezone: schema.maybe(
schema.string({
meta: {
description: 'The timezone of the schedule. The default timezone is UTC.',
},
})
),
recurring: schema.maybe(
schema.object({
end: schema.maybe(
schema.string({
meta: {
description:
'The end date of a recurring schedule, provided in ISO 8601 format and set to the UTC timezone. For example: `2025-04-01T00:00:00.000Z`.',
},
})
),
every: schema.maybe(
schema.string({
meta: {
description:
'The interval and frequency of a recurring schedule. It allows values in `<integer><unit>` format. `<unit>` is one of `d`, `w`, `M`, or `y` for days, weeks, months, years. For example: `15d`, `2w`, `3m`, `1y`.',
},
})
),
onWeekDay: schema.maybe(
schema.arrayOf(schema.string(), {
meta: {
description:
'The specific days of the week (`[MO,TU,WE,TH,FR,SA,SU]`) or nth day of month (`[+1MO, -3FR, +2WE, -4SA, -5SU]`) for a recurring schedule.',
},
})
),
onMonthDay: schema.maybe(
schema.arrayOf(schema.number(), {
meta: {
description:
'The specific days of the month for a recurring schedule. Valid values are 1-31.',
},
})
),
onMonth: schema.maybe(
schema.arrayOf(schema.number(), {
meta: {
description: 'The specific months for a recurring schedule. Valid values are 1-12.',
},
})
),
occurrences: schema.maybe(
schema.number({
meta: {
description: 'The total number of recurrences of the schedule.',
},
})
),
})
),
});

View file

@ -78,14 +78,14 @@ describe('transformCustomScheduleToRRule', () => {
transformCustomScheduleToRRule({
duration: '30m',
start: '2025-02-17T19:04:46.320Z',
recurring: { every: '1d', end: '2025-05-17T05:05:00.000Z', onWeekDay: ['Mo', 'FR'] },
recurring: { every: '1d', end: '2025-05-17T05:05:00.000Z', onWeekDay: ['MO', 'FR'] },
})
).toEqual({
duration: 1800000,
rRule: {
bymonth: undefined,
bymonthday: undefined,
byweekday: ['Mo', 'FR'],
byweekday: ['MO', 'FR'],
count: undefined,
dtstart: '2025-02-17T19:04:46.320Z',
freq: 3,

View file

@ -41,7 +41,7 @@ describe('transformRRuleToCustomSchedule', () => {
transformRRuleToCustomSchedule({
duration: 1800000,
rRule: {
byweekday: ['Mo', 'FR'],
byweekday: ['MO', 'FR'],
dtstart: '2025-02-17T19:04:46.320Z',
freq: 1,
interval: 6,
@ -52,7 +52,7 @@ describe('transformRRuleToCustomSchedule', () => {
).toEqual({
duration: '30m',
start: '2025-02-17T19:04:46.320Z',
recurring: { every: '6M', end: '2025-05-17T05:05:00.000Z', onWeekDay: ['Mo', 'FR'] },
recurring: { every: '6M', end: '2025-05-17T05:05:00.000Z', onWeekDay: ['MO', 'FR'] },
timezone: 'UTC',
});
});
@ -62,7 +62,7 @@ describe('transformRRuleToCustomSchedule', () => {
transformRRuleToCustomSchedule({
duration: 1800000,
rRule: {
byweekday: ['Mo', 'FR'],
byweekday: ['MO', 'FR'],
dtstart: '2025-02-17T19:04:46.320Z',
freq: 3,
interval: 1,
@ -73,7 +73,7 @@ describe('transformRRuleToCustomSchedule', () => {
).toEqual({
duration: '30m',
start: '2025-02-17T19:04:46.320Z',
recurring: { every: '1d', end: '2025-05-17T05:05:00.000Z', onWeekDay: ['Mo', 'FR'] },
recurring: { every: '1d', end: '2025-05-17T05:05:00.000Z', onWeekDay: ['MO', 'FR'] },
timezone: 'UTC',
});
});

View file

@ -44,14 +44,10 @@ const getDurationInString = (duration: number): string => {
return `${durationInSeconds}s`;
};
export const transformRRuleToCustomSchedule = (snoozeSchedule?: {
export const transformRRuleToCustomSchedule = (snoozeSchedule: {
duration: number;
rRule: RRule;
}): ScheduleRequest | undefined => {
if (!snoozeSchedule) {
return;
}
}): ScheduleRequest => {
const { rRule, duration } = snoozeSchedule;
const transformedFrequency = transformFrequencyToEvery(rRule.freq as Frequency);
const transformedDuration = getDurationInString(duration);

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import type { scheduleRequestSchemaV1 } from '..';
import type { scheduleRequestSchemaV1, scheduleResponseSchemaV1 } from '..';
export type ScheduleRequest = TypeOf<typeof scheduleRequestSchemaV1>;
export type ScheduleResponse = TypeOf<typeof scheduleResponseSchemaV1>;

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { HttpSetup } from '@kbn/core/public';
import type { MaintenanceWindowResponse } from '../../../common/routes/maintenance_window/response';
import type { MaintenanceWindowResponse } from '../../../common/routes/maintenance_window/internal/response';
import type { MaintenanceWindow } from '../../../common';
import { INTERNAL_BASE_ALERTING_API_PATH } from '../../../common';
import { transformMaintenanceWindowResponse } from './transform_maintenance_window_response';

View file

@ -6,8 +6,8 @@
*/
import type { HttpSetup } from '@kbn/core/public';
import type { MaintenanceWindow } from '../../../common';
import type { CreateMaintenanceWindowRequestBody } from '../../../common/routes/maintenance_window/apis/create';
import type { MaintenanceWindowResponse } from '../../../common/routes/maintenance_window/response';
import type { CreateMaintenanceWindowRequestBody } from '../../../common/routes/maintenance_window/internal/apis/create';
import type { MaintenanceWindowResponse } from '../../../common/routes/maintenance_window/internal/response';
import { INTERNAL_BASE_ALERTING_API_PATH } from '../../../common';
import { transformMaintenanceWindowResponse } from './transform_maintenance_window_response';

View file

@ -7,7 +7,7 @@
import type { HttpSetup } from '@kbn/core/public';
import type { MaintenanceWindow, MaintenanceWindowStatus } from '../../../common';
import type { FindMaintenanceWindowsResponse } from '../../../common/routes/maintenance_window/apis/find';
import type { FindMaintenanceWindowsResponse } from '../../../common/routes/maintenance_window/internal/apis/find';
import { transformMaintenanceWindowResponse } from './transform_maintenance_window_response';
import { INTERNAL_BASE_ALERTING_API_PATH } from '../../../common';

Some files were not shown because too many files have changed in this diff Show more