"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getMigrations = getMigrations; var _uuid = require("uuid"); var _server = require("@kbn/core/server"); var _task_type_dictionary = require("../task_type_dictionary"); var _task = require("../task"); /* * 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. */ function getMigrations() { return { '7.4.0': executeMigrationWithErrorHandling(doc => ({ ...doc, updated_at: new Date().toISOString() }), '7.4.0'), '7.6.0': executeMigrationWithErrorHandling(moveIntervalIntoSchedule, '7.6.0'), '8.0.0': executeMigrationWithErrorHandling(pipeMigrations(alertingTaskLegacyIdToSavedObjectIds, actionsTasksLegacyIdToSavedObjectIds), '8.0.0'), '8.2.0': executeMigrationWithErrorHandling(pipeMigrations(resetAttemptsAndStatusForTheTasksWithoutSchedule, resetUnrecognizedStatus), '8.2.0'), '8.5.0': executeMigrationWithErrorHandling(pipeMigrations(addEnabledField), '8.5.0'), '8.8.0': executeMigrationWithErrorHandling(pipeMigrations(addAlertUUID), '8.8.0') }; } function executeMigrationWithErrorHandling(migrationFunc, version) { return (doc, context) => { try { return migrationFunc(doc, context); } catch (ex) { context.log.error(`savedObject ${version} migration failed for task instance ${doc.id} with error: ${ex.message}`, { migrations: { taskInstanceDocument: doc } }); throw ex; } }; } function alertingTaskLegacyIdToSavedObjectIds(doc) { if (doc.attributes.taskType.startsWith('alerting:')) { let params = {}; params = JSON.parse(doc.attributes.params); if (params.alertId && params.spaceId && params.spaceId !== 'default') { const newId = _server.SavedObjectsUtils.getConvertedObjectId(params.spaceId, 'alert', params.alertId); return { ...doc, attributes: { ...doc.attributes, params: JSON.stringify({ ...params, alertId: newId // eslint-disable-next-line @typescript-eslint/no-explicit-any }) } }; } } return doc; } function actionsTasksLegacyIdToSavedObjectIds(doc) { if (doc.attributes.taskType.startsWith('actions:')) { let params = {}; params = JSON.parse(doc.attributes.params); if (params.actionTaskParamsId && params.spaceId && params.spaceId !== 'default') { const newId = _server.SavedObjectsUtils.getConvertedObjectId(params.spaceId, 'action_task_params', params.actionTaskParamsId); return { ...doc, attributes: { ...doc.attributes, params: JSON.stringify({ ...params, actionTaskParamsId: newId // eslint-disable-next-line @typescript-eslint/no-explicit-any }) } }; } } return doc; } function moveIntervalIntoSchedule({ attributes: { interval, ...attributes }, ...doc }) { return { ...doc, attributes: { ...attributes, ...(interval ? { schedule: { interval } } : {}) } }; } function resetUnrecognizedStatus(doc) { var _doc$attributes; const status = doc === null || doc === void 0 ? void 0 : (_doc$attributes = doc.attributes) === null || _doc$attributes === void 0 ? void 0 : _doc$attributes.status; if (status && status === 'unrecognized') { const taskType = doc.attributes.taskType; // If task type is in the REMOVED_TYPES list, maintain "unrecognized" status if (_task_type_dictionary.REMOVED_TYPES.indexOf(taskType) >= 0) { return doc; } return { ...doc, attributes: { ...doc.attributes, status: 'idle' } }; } return doc; } function pipeMigrations(...migrations) { return doc => migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc); } function resetAttemptsAndStatusForTheTasksWithoutSchedule(doc) { if (doc.attributes.taskType.startsWith('alerting:')) { var _doc$attributes$sched; if (!((_doc$attributes$sched = doc.attributes.schedule) !== null && _doc$attributes$sched !== void 0 && _doc$attributes$sched.interval) && (doc.attributes.status === _task.TaskStatus.Failed || doc.attributes.status === _task.TaskStatus.Running)) { return { ...doc, attributes: { ...doc.attributes, attempts: 0, status: _task.TaskStatus.Idle } }; } } return doc; } function addEnabledField(doc) { if (doc.attributes.status === _task.TaskStatus.Failed || doc.attributes.status === _task.TaskStatus.Unrecognized) { return doc; } return { ...doc, attributes: { ...doc.attributes, enabled: true } }; } function addAlertUUID(doc) { if (!doc.attributes.taskType.startsWith('alerting:')) return doc; if (!doc.attributes.state) return doc; const taskState = JSON.parse(doc.attributes.state); const ruleState = taskState === null || taskState === void 0 ? void 0 : taskState.alertTypeState; if (!ruleState) return doc; // get existing alert uuid's from the rule registry's rule state wrapper const alertToTrackedMap = getAlertsToTrackedMap(ruleState); // we are iterating over two collections of alerts, so in case there are // duplicates, keep track of all uuid's assigned, so the same one will be used const currentUUIDs = new Map(); // add the uuids to the framework's meta object; the objects are mutated in-line addAlertUUIDsToAlerts(taskState.alertInstances, alertToTrackedMap, currentUUIDs); addAlertUUIDsToAlerts(taskState.alertRecoveredInstances, alertToTrackedMap, currentUUIDs); return { ...doc, attributes: { ...doc.attributes, state: JSON.stringify(taskState) } }; } // mutates alerts passed in function addAlertUUIDsToAlerts(alerts, alertToTrackedMap, currentUUIDs) { if (!alerts) return; for (const [id, alert] of Object.entries(alerts)) { if (!alert.meta) alert.meta = {}; // get alert info from tracked map (rule registry) const trackedAlert = alertToTrackedMap.get(id); // get uuid for current alert, if we've already seen it const recentUUID = currentUUIDs.get(id); if (trackedAlert !== null && trackedAlert !== void 0 && trackedAlert.alertUuid) { alert.meta.uuid = trackedAlert.alertUuid; } else if (recentUUID) { alert.meta.uuid = recentUUID; } else { alert.meta.uuid = (0, _uuid.v4)(); } currentUUIDs.set(id, alert.meta.uuid); } } // gets a map of alertId => tracked alert state, which is from the // rule registry wrapper, which contains the uuid and other info function getAlertsToTrackedMap(ruleState) { const result = new Map(); if (!isRuleRegistryWrappedState(ruleState)) return result; return new Map([...Object.entries(ruleState.trackedAlerts || {}), ...Object.entries(ruleState.trackedAlertsRecovered || {})]); } function isRuleRegistryWrappedState(ruleState) { return ruleState.wrapped != null && (ruleState.trackedAlerts != null || ruleState.trackedAlertsRecovered != null); }