From c47cdbf1ed2166f4fc96a593bdd429c608f7577d Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:05:26 -0400 Subject: [PATCH] [8.10] chore(slo): general enhancement (#164723) (#165032) # Backport This will backport the following commits from `main` to `8.10`: - [chore(slo): general enhancement (#164723)](https://github.com/elastic/kibana/pull/164723) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Kevin Delemme --- .../kbn-slo-schema/src/rest_specs/slo.ts | 5 - .../hooks/slo/use_fetch_active_alerts.ts | 1 + .../hooks/slo/use_fetch_global_diagnosis.ts | 85 ++++------- .../slo/use_fetch_index_pattern_fields.ts | 2 +- .../hooks/slo/use_fetch_rules_for_slo.ts | 7 +- .../pages/slos_welcome/slos_welcome.test.tsx | 25 +++- .../pages/slos_welcome/slos_welcome.tsx | 9 +- .../register_observability_rule_types.ts | 6 +- .../slo_summary_settings_template.ts | 2 +- .../observability/server/routes/slo/route.ts | 19 +-- .../observability/server/saved_objects/slo.ts | 2 +- .../server/services/slo/get_diagnosis.ts | 137 +----------------- .../server/services/slo/transform_manager.ts | 2 +- 13 files changed, 79 insertions(+), 223 deletions(-) diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts index 4e1aa86aff6e26..17b8e86d9fc5ad 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts @@ -188,10 +188,6 @@ const findSloDefinitionsParamsSchema = t.type({ */ const findSloDefinitionsResponseSchema = t.array(sloResponseSchema); -const getSLODiagnosisParamsSchema = t.type({ - path: t.type({ id: t.string }), -}); - const getSLOBurnRatesResponseSchema = t.type({ burnRates: t.array( t.type({ @@ -277,7 +273,6 @@ export { findSLOResponseSchema, getPreviewDataParamsSchema, getPreviewDataResponseSchema, - getSLODiagnosisParamsSchema, getSLOParamsSchema, getSLOResponseSchema, fetchHistoricalSummaryParamsSchema, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts index 601fc8f024a89d..7f4e6fdce5b2be 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts @@ -135,6 +135,7 @@ export function useFetchActiveAlerts({ sloIdsAndInstanceIds = [] }: Params): Use } }, refetchOnWindowFocus: false, + enabled: Boolean(sloIdsAndInstanceIds.length), }); return { diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts index 94ec7c625a1b1c..45ef877bf2472f 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_global_diagnosis.ts @@ -5,32 +5,17 @@ * 2.0. */ -import { - QueryObserverResult, - RefetchOptions, - RefetchQueryFilters, - useQuery, -} from '@tanstack/react-query'; +import type { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import type { PublicLicenseJSON } from '@kbn/licensing-plugin/public'; -import type { - SecurityGetUserPrivilegesResponse, - TransformGetTransformStatsResponse, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { useQuery } from '@tanstack/react-query'; import { useKibana } from '../../utils/kibana_react'; import { convertErrorForUseInToast } from './helpers/convert_error_for_use_in_toast'; import { sloKeys } from './query_key_factory'; interface SloGlobalDiagnosisResponse { licenseAndFeatures: PublicLicenseJSON; - userPrivileges: SecurityGetUserPrivilegesResponse; - sloResources: { - [x: string]: 'OK' | 'NOT_OK'; - }; - sloSummaryResources: { - [x: string]: 'OK' | 'NOT_OK'; - }; - sloSummaryTransformsStats: TransformGetTransformStatsResponse; + userPrivileges: { write: SecurityHasPrivilegesResponse; read: SecurityHasPrivilegesResponse }; } export interface UseFetchSloGlobalDiagnoseResponse { @@ -39,10 +24,7 @@ export interface UseFetchSloGlobalDiagnoseResponse { isRefetching: boolean; isSuccess: boolean; isError: boolean; - globalSloDiagnosis: SloGlobalDiagnosisResponse | undefined; - refetch: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise>; + data: SloGlobalDiagnosisResponse | undefined; } export function useFetchSloGlobalDiagnosis(): UseFetchSloGlobalDiagnoseResponse { @@ -51,44 +33,41 @@ export function useFetchSloGlobalDiagnosis(): UseFetchSloGlobalDiagnoseResponse notifications: { toasts }, } = useKibana().services; - const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( - { - queryKey: sloKeys.globalDiagnosis(), - queryFn: async ({ signal }) => { - try { - const response = await http.get( - '/internal/observability/slos/_diagnosis', - { - query: {}, - signal, - } - ); + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: sloKeys.globalDiagnosis(), + queryFn: async ({ signal }) => { + try { + const response = await http.get( + '/internal/observability/slos/_diagnosis', + { + query: {}, + signal, + } + ); - return response; - } catch (error) { - throw convertErrorForUseInToast(error); - } - }, - keepPreviousData: true, - refetchOnWindowFocus: false, - retry: false, - onError: (error: Error) => { - toasts.addError(error, { - title: i18n.translate('xpack.observability.slo.globalDiagnosis.errorNotification', { - defaultMessage: 'You do not have the right permissions to use this feature.', - }), - }); - }, - } - ); + return response; + } catch (error) { + throw convertErrorForUseInToast(error); + } + }, + keepPreviousData: true, + refetchOnWindowFocus: false, + retry: false, + onError: (error: Error) => { + toasts.addError(error, { + title: i18n.translate('xpack.observability.slo.globalDiagnosis.errorNotification', { + defaultMessage: 'You do not have the right permissions to use this feature.', + }), + }); + }, + }); return { - globalSloDiagnosis: data, + data, isLoading, isInitialLoading, isRefetching, isSuccess, isError, - refetch, }; } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts index 2f51e4d7faf26c..3363d501fae22c 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_index_pattern_fields.ts @@ -34,7 +34,7 @@ export function useFetchIndexPatternFields( return []; } try { - return await dataViews.getFieldsForWildcard({ pattern: indexPattern }); + return await dataViews.getFieldsForWildcard({ pattern: indexPattern, allowNoIndex: true }); } catch (error) { throw new Error(`Something went wrong. Error: ${error}`); } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts index eab7a9a65df8a8..2344b3aa8d176c 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_rules_for_slo.ts @@ -52,8 +52,7 @@ export function useFetchRulesForSlo({ sloIds = [] }: Params): UseFetchRulesForSl queryFn: async () => { try { const body = JSON.stringify({ - filter: - sloIds?.map((sloId) => `alert.attributes.params.sloId:${sloId}`).join(' or ') ?? '', + filter: sloIds.map((sloId) => `alert.attributes.params.sloId:${sloId}`).join(' or '), fields: ['params.sloId', 'name'], per_page: 1000, }); @@ -62,7 +61,7 @@ export function useFetchRulesForSlo({ sloIds = [] }: Params): UseFetchRulesForSl body, }); - const init = sloIds?.reduce((acc, sloId) => ({ ...acc, [sloId]: [] }), {}); + const init = sloIds.reduce((acc, sloId) => ({ ...acc, [sloId]: [] }), {}); return response.data.reduce( (acc, rule) => ({ @@ -75,7 +74,7 @@ export function useFetchRulesForSlo({ sloIds = [] }: Params): UseFetchRulesForSl // ignore error for retrieving slos } }, - enabled: Boolean(sloIds?.length), + enabled: Boolean(sloIds.length), refetchOnWindowFocus: false, keepPreviousData: true, } diff --git a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx index 155e49c3976fc1..fbeae4cb872b26 100644 --- a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx +++ b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.test.tsx @@ -59,7 +59,9 @@ describe('SLOs Welcome Page', () => { useFetchSloListMock.mockReturnValue({ isLoading: false, sloList: emptySloList }); useLicenseMock.mockReturnValue({ hasAtLeast: () => false }); useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + data: { + userPrivileges: { write: { has_all_requested: true }, read: { has_all_requested: true } }, + }, }); render(); @@ -104,7 +106,12 @@ describe('SLOs Welcome Page', () => { hasReadCapabilities: true, }); useGlobalDiagnosisMock.mockReturnValue({ - isError: true, + data: { + userPrivileges: { + write: { has_all_requested: false }, + read: { has_all_requested: true }, + }, + }, }); render(); @@ -116,7 +123,12 @@ describe('SLOs Welcome Page', () => { it('should display the welcome message with a Create new SLO button which should navigate to the SLO Creation page', async () => { useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + data: { + userPrivileges: { + write: { has_all_requested: true }, + read: { has_all_requested: true }, + }, + }, }); render(); @@ -136,7 +148,12 @@ describe('SLOs Welcome Page', () => { beforeEach(() => { useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + data: { + userPrivileges: { + write: { has_all_requested: true }, + read: { has_all_requested: true }, + }, + }, }); }); diff --git a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx index 2f0ef6ad1389ee..5c4317cd4e138c 100644 --- a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx +++ b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx @@ -34,7 +34,7 @@ export function SlosWelcomePage() { http: { basePath }, } = useKibana().services; const { hasWriteCapabilities } = useCapabilities(); - const { isError: hasErrorInGlobalDiagnosis } = useFetchSloGlobalDiagnosis(); + const { data: globalDiagnosis } = useFetchSloGlobalDiagnosis(); const { ObservabilityPageTemplate } = usePluginContext(); const { hasAtLeast } = useLicense(); @@ -43,12 +43,15 @@ export function SlosWelcomePage() { const { isLoading, sloList } = useFetchSloList(); const { total } = sloList || { total: 0 }; + const hasRequiredWritePrivileges = !!globalDiagnosis?.userPrivileges.write.has_all_requested; + const hasRequiredReadPrivileges = !!globalDiagnosis?.userPrivileges.read.has_all_requested; + const handleClickCreateSlo = () => { navigateToUrl(basePath.prepend(paths.observability.sloCreate)); }; const hasSlosAndHasPermissions = - total > 0 && hasAtLeast('platinum') === true && !hasErrorInGlobalDiagnosis; + total > 0 && hasAtLeast('platinum') === true && hasRequiredReadPrivileges; useEffect(() => { if (hasSlosAndHasPermissions) { @@ -115,7 +118,7 @@ export function SlosWelcomePage() { fill color="primary" onClick={handleClickCreateSlo} - disabled={!hasWriteCapabilities || hasErrorInGlobalDiagnosis} + disabled={!hasWriteCapabilities || !hasRequiredWritePrivileges} > {i18n.translate('xpack.observability.slo.sloList.welcomePrompt.buttonLabel', { defaultMessage: 'Create SLO', diff --git a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts index 18d2ae5aa998b0..c06bd84e02c778 100644 --- a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts +++ b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts @@ -9,7 +9,7 @@ import { lazy } from 'react'; import { i18n } from '@kbn/i18n'; import { ALERT_REASON } from '@kbn/rule-data-utils'; -import { SLO_ID_FIELD } from '../../common/field_names/slo'; +import { SLO_ID_FIELD, SLO_INSTANCE_ID_FIELD } from '../../common/field_names/slo'; import { ConfigSchema } from '../plugin'; import { ObservabilityRuleTypeRegistry } from './create_observability_rule_type_registry'; import { @@ -86,7 +86,9 @@ export const registerObservabilityRuleTypes = ( format: ({ fields }) => { return { reason: fields[ALERT_REASON] ?? '-', - link: `/app/observability/slos/${fields[SLO_ID_FIELD]}`, + link: `/app/observability/slos/${fields[SLO_ID_FIELD]}?instanceId=${ + fields[SLO_INSTANCE_ID_FIELD] ?? '*' + }`, }; }, iconClass: 'bell', diff --git a/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts b/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts index 286434003f5409..336b7d9e0c35cb 100644 --- a/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts +++ b/x-pack/plugins/observability/server/assets/component_templates/slo_summary_settings_template.ts @@ -11,7 +11,7 @@ export const getSLOSummarySettingsTemplate = (name: string) => ({ name, template: { settings: { - auto_expand_replicas: '0-all', + auto_expand_replicas: '0-1', hidden: true, }, }, diff --git a/x-pack/plugins/observability/server/routes/slo/route.ts b/x-pack/plugins/observability/server/routes/slo/route.ts index e991f2b6a9d4f8..f77f173675c682 100644 --- a/x-pack/plugins/observability/server/routes/slo/route.ts +++ b/x-pack/plugins/observability/server/routes/slo/route.ts @@ -15,7 +15,6 @@ import { findSLOParamsSchema, getPreviewDataParamsSchema, getSLOBurnRatesParamsSchema, - getSLODiagnosisParamsSchema, getSLOInstancesParamsSchema, getSLOParamsSchema, manageSLOParamsSchema, @@ -35,7 +34,7 @@ import { import { FetchHistoricalSummary } from '../../services/slo/fetch_historical_summary'; import { FindSLODefinitions } from '../../services/slo/find_slo_definitions'; import { getBurnRates } from '../../services/slo/get_burn_rates'; -import { getGlobalDiagnosis, getSloDiagnosis } from '../../services/slo/get_diagnosis'; +import { getGlobalDiagnosis } from '../../services/slo/get_diagnosis'; import { GetPreviewData } from '../../services/slo/get_preview_data'; import { GetSLOInstances } from '../../services/slo/get_slo_instances'; import { DefaultHistoricalSummaryClient } from '../../services/slo/historical_summary_client'; @@ -310,21 +309,6 @@ const getDiagnosisRoute = createObservabilityServerRoute({ }, }); -const getSloDiagnosisRoute = createObservabilityServerRoute({ - endpoint: 'GET /internal/observability/slos/{id}/_diagnosis', - options: { - tags: [], - }, - params: getSLODiagnosisParamsSchema, - handler: async ({ context, params }) => { - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; - const repository = new KibanaSavedObjectsSLORepository(soClient); - - return getSloDiagnosis(params.path.id, { esClient, repository }); - }, -}); - const getSloBurnRates = createObservabilityServerRoute({ endpoint: 'POST /internal/observability/slos/{id}/_burn_rates', options: { @@ -375,7 +359,6 @@ export const sloRouteRepository = { ...getSLORoute, ...updateSLORoute, ...getDiagnosisRoute, - ...getSloDiagnosisRoute, ...getSloBurnRates, ...getPreviewData, ...getSLOInstancesRoute, diff --git a/x-pack/plugins/observability/server/saved_objects/slo.ts b/x-pack/plugins/observability/server/saved_objects/slo.ts index 508f2ea8aae7a5..41cb509d837556 100644 --- a/x-pack/plugins/observability/server/saved_objects/slo.ts +++ b/x-pack/plugins/observability/server/saved_objects/slo.ts @@ -57,7 +57,7 @@ export const slo: SavedObjectsType = { }, management: { displayName: 'SLO', - importableAndExportable: true, + importableAndExportable: false, getTitle(sloSavedObject: SavedObject) { return `SLO: [${sloSavedObject.attributes.name}]`; }, diff --git a/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts b/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts index 4bdf43e1433424..697d3ceb560df0 100644 --- a/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts +++ b/x-pack/plugins/observability/server/services/slo/get_diagnosis.ts @@ -5,147 +5,24 @@ * 2.0. */ -import { errors } from '@elastic/elasticsearch'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server'; -import { - getSLOTransformId, - SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_INDEX_TEMPLATE_NAME, - SLO_INGEST_PIPELINE_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_SUMMARY_INDEX_TEMPLATE_NAME, - SLO_SUMMARY_TRANSFORM_NAME_PREFIX, -} from '../../assets/constants'; -import { SLO } from '../../domain/models'; -import { SLORepository } from './slo_repository'; - -const OK = 'OK'; -const NOT_OK = 'NOT_OK'; export async function getGlobalDiagnosis( esClient: ElasticsearchClient, licensing: LicensingApiRequestHandlerContext ) { const licenseInfo = licensing.license.toJSON(); - const userPrivileges = await esClient.security.getUserPrivileges(); - const sloResources = await getSloResourcesDiagnosis(esClient); - const sloSummaryResources = await getSloSummaryResourcesDiagnosis(esClient); - - const sloSummaryTransformsStats = await esClient.transform.getTransformStats({ - transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}*`, - allow_no_match: true, - }); - - return { - licenseAndFeatures: licenseInfo, - userPrivileges, - sloResources, - sloSummaryResources, - sloSummaryTransformsStats, - }; -} - -export async function getSloDiagnosis( - sloId: string, - services: { esClient: ElasticsearchClient; repository: SLORepository } -) { - const { esClient, repository } = services; - - const sloResources = await getSloResourcesDiagnosis(esClient); - const sloSummaryResources = await getSloSummaryResourcesDiagnosis(esClient); - - let slo: SLO | undefined; - try { - slo = await repository.findById(sloId); - } catch (err) { - // noop - } - - const sloTransformStats = await esClient.transform.getTransformStats({ - transform_id: getSLOTransformId(sloId, slo?.revision ?? 1), - allow_no_match: true, + const userWritePrivileges = await esClient.security.hasPrivileges({ + cluster: ['manage_transform'], + index: [{ names: '.slo-*', privileges: ['all'] }], }); - - const sloSummaryTransformsStats = await esClient.transform.getTransformStats({ - transform_id: `${SLO_SUMMARY_TRANSFORM_NAME_PREFIX}*`, - allow_no_match: true, + const userReadPrivileges = await esClient.security.hasPrivileges({ + index: [{ names: '.slo-*', privileges: ['read'] }], }); return { - sloResources, - sloSummaryResources, - slo: slo ?? NOT_OK, - sloTransformStats, - sloSummaryTransformsStats, + licenseAndFeatures: licenseInfo, + userPrivileges: { write: userWritePrivileges, read: userReadPrivileges }, }; } - -async function getSloResourcesDiagnosis(esClient: ElasticsearchClient) { - try { - const indexTemplateExists = await esClient.indices.existsIndexTemplate({ - name: SLO_INDEX_TEMPLATE_NAME, - }); - - const mappingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - }); - - const settingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - }); - - let ingestPipelineExists = true; - try { - await esClient.ingest.getPipeline({ id: SLO_INGEST_PIPELINE_NAME }); - } catch (err) { - ingestPipelineExists = false; - throw err; - } - - return { - [SLO_INDEX_TEMPLATE_NAME]: indexTemplateExists ? OK : NOT_OK, - [SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME]: mappingsTemplateExists ? OK : NOT_OK, - [SLO_COMPONENT_TEMPLATE_SETTINGS_NAME]: settingsTemplateExists ? OK : NOT_OK, - [SLO_INGEST_PIPELINE_NAME]: ingestPipelineExists ? OK : NOT_OK, - }; - } catch (err) { - if ( - err instanceof errors.ResponseError && - (err.statusCode === 403 || err.meta.statusCode === 403) - ) { - throw new Error('Insufficient permissions to access Elasticsearch Cluster', { cause: err }); - } - } -} - -async function getSloSummaryResourcesDiagnosis(esClient: ElasticsearchClient) { - try { - const indexTemplateExists = await esClient.indices.existsIndexTemplate({ - name: SLO_SUMMARY_INDEX_TEMPLATE_NAME, - }); - - const mappingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - }); - - const settingsTemplateExists = await esClient.cluster.existsComponentTemplate({ - name: SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - }); - - return { - [SLO_SUMMARY_INDEX_TEMPLATE_NAME]: indexTemplateExists ? OK : NOT_OK, - [SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME]: mappingsTemplateExists ? OK : NOT_OK, - [SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME]: settingsTemplateExists ? OK : NOT_OK, - }; - } catch (err) { - if ( - err instanceof errors.ResponseError && - (err.statusCode === 403 || err.meta.statusCode === 403) - ) { - throw new Error('Insufficient permissions to access Elasticsearch Cluster', { cause: err }); - } - } -} diff --git a/x-pack/plugins/observability/server/services/slo/transform_manager.ts b/x-pack/plugins/observability/server/services/slo/transform_manager.ts index 3bd56669046ac4..14b600a746cac8 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_manager.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_manager.ts @@ -65,7 +65,7 @@ export class DefaultTransformManager implements TransformManager { await retryTransientEsErrors( () => this.esClient.transform.stopTransform( - { transform_id: transformId, wait_for_completion: true }, + { transform_id: transformId, wait_for_completion: true, force: true }, { ignore: [404] } ), { logger: this.logger }