Skip to content

Commit 4b8b5cf

Browse files
kibanamachineJoseLuisGJelasticmachine
authored
[8.19] [Search][Query Rules UI] Create ruleset flow (#219674) (#220225)
# Backport This will backport the following commits from `main` to `8.19`: - [[Search][Query Rules UI] Create ruleset flow (#219674)](#219674) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"José Luis González","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-05-06T10:54:48Z","message":"[Search][Query Rules UI] Create ruleset flow (#219674)\n\n## Summary\n\nThis PR enables a Query Rules modal to ask the ruleset name to be\ncreated. Once created with a default data we take users to the ruleset\ndetail page for now. Later we should also open the Flyout fin order to\ncreate its first rule beloning to that ruleset.\n\n\nhttps://github.com/user-attachments/assets/4777140d-629e-4509-99e2-734fd1359261\n\nFor now providing default rules values:\n\n```JSX\n...\n rules: [\n {\n rule_id: 'rule1',\n type: 'pinned',\n criteria: [\n {\n type: 'fuzzy',\n metadata: 'query_string',\n values: ['puggles', 'pugs'],\n },\n ],\n actions: {\n docs: [\n {\n _index: 'my-index-000001',\n _id: 'id1',\n },\n ],\n },\n },\n ],\n...\n```\n\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [ ] Any text added follows [EUI's writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\nsentence case text and includes [i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n- [ ]\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\nwas added for features that require explanation or tutorials\n- [ ] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] If a plugin configuration key changed, check if it needs to be\nallowlisted in the cloud and added to the [docker\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\n- [ ] This was checked for breaking HTTP API changes, and any breaking\nchanges have been approved by the breaking-change committee. The\n`release_note:breaking` label should be applied in these situations.\n- [ ] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n\n### Identify risks\n\nDoes this PR introduce any risks? For example, consider risks like hard\nto test bugs, performance regression, potential of data loss.\n\nDescribe the risk, its severity, and mitigation for each identified\nrisk. Invite stakeholders and evaluate how to proceed before merging.\n\n- [ ] [See some risk\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)\n- [ ] ...\n\n---------\n\nCo-authored-by: Elastic Machine <[email protected]>","sha":"852966c73d73b8a185f8a4168086217efa088b58","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Search","backport:version","v9.1.0","v8.19.0"],"title":"[Search][Query Rules UI] Create ruleset flow","number":219674,"url":"https://github.com/elastic/kibana/pull/219674","mergeCommit":{"message":"[Search][Query Rules UI] Create ruleset flow (#219674)\n\n## Summary\n\nThis PR enables a Query Rules modal to ask the ruleset name to be\ncreated. Once created with a default data we take users to the ruleset\ndetail page for now. Later we should also open the Flyout fin order to\ncreate its first rule beloning to that ruleset.\n\n\nhttps://github.com/user-attachments/assets/4777140d-629e-4509-99e2-734fd1359261\n\nFor now providing default rules values:\n\n```JSX\n...\n rules: [\n {\n rule_id: 'rule1',\n type: 'pinned',\n criteria: [\n {\n type: 'fuzzy',\n metadata: 'query_string',\n values: ['puggles', 'pugs'],\n },\n ],\n actions: {\n docs: [\n {\n _index: 'my-index-000001',\n _id: 'id1',\n },\n ],\n },\n },\n ],\n...\n```\n\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [ ] Any text added follows [EUI's writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\nsentence case text and includes [i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n- [ ]\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\nwas added for features that require explanation or tutorials\n- [ ] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] If a plugin configuration key changed, check if it needs to be\nallowlisted in the cloud and added to the [docker\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\n- [ ] This was checked for breaking HTTP API changes, and any breaking\nchanges have been approved by the breaking-change committee. The\n`release_note:breaking` label should be applied in these situations.\n- [ ] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n\n### Identify risks\n\nDoes this PR introduce any risks? For example, consider risks like hard\nto test bugs, performance regression, potential of data loss.\n\nDescribe the risk, its severity, and mitigation for each identified\nrisk. Invite stakeholders and evaluate how to proceed before merging.\n\n- [ ] [See some risk\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)\n- [ ] ...\n\n---------\n\nCo-authored-by: Elastic Machine <[email protected]>","sha":"852966c73d73b8a185f8a4168086217efa088b58"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/219674","number":219674,"mergeCommit":{"message":"[Search][Query Rules UI] Create ruleset flow (#219674)\n\n## Summary\n\nThis PR enables a Query Rules modal to ask the ruleset name to be\ncreated. Once created with a default data we take users to the ruleset\ndetail page for now. Later we should also open the Flyout fin order to\ncreate its first rule beloning to that ruleset.\n\n\nhttps://github.com/user-attachments/assets/4777140d-629e-4509-99e2-734fd1359261\n\nFor now providing default rules values:\n\n```JSX\n...\n rules: [\n {\n rule_id: 'rule1',\n type: 'pinned',\n criteria: [\n {\n type: 'fuzzy',\n metadata: 'query_string',\n values: ['puggles', 'pugs'],\n },\n ],\n actions: {\n docs: [\n {\n _index: 'my-index-000001',\n _id: 'id1',\n },\n ],\n },\n },\n ],\n...\n```\n\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [ ] Any text added follows [EUI's writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\nsentence case text and includes [i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n- [ ]\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\nwas added for features that require explanation or tutorials\n- [ ] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] If a plugin configuration key changed, check if it needs to be\nallowlisted in the cloud and added to the [docker\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\n- [ ] This was checked for breaking HTTP API changes, and any breaking\nchanges have been approved by the breaking-change committee. The\n`release_note:breaking` label should be applied in these situations.\n- [ ] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n\n### Identify risks\n\nDoes this PR introduce any risks? For example, consider risks like hard\nto test bugs, performance regression, potential of data loss.\n\nDescribe the risk, its severity, and mitigation for each identified\nrisk. Invite stakeholders and evaluate how to proceed before merging.\n\n- [ ] [See some risk\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)\n- [ ] ...\n\n---------\n\nCo-authored-by: Elastic Machine <[email protected]>","sha":"852966c73d73b8a185f8a4168086217efa088b58"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: José Luis González <[email protected]> Co-authored-by: Elastic Machine <[email protected]>
1 parent c1ef0c7 commit 4b8b5cf

File tree

10 files changed

+396
-16
lines changed

10 files changed

+396
-16
lines changed

x-pack/solutions/search/plugins/search_query_rules/common/api_routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ export const PLUGIN_ROUTE_ROOT = '/app/elasticsearch/query_rules';
99

1010
export enum APIRoutes {
1111
QUERY_RULES_SETS = '/internal/search_query_rules/query_rules_sets',
12-
QUERY_RULES_RULESET_FETCH = '/internal/search_query_rules/ruleset/{ruleset_id}',
12+
QUERY_RULES_RULESET_ID = '/internal/search_query_rules/ruleset/{ruleset_id}',
1313
}

x-pack/solutions/search/plugins/search_query_rules/common/constants.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ PUT /_query_rules/my-ruleset
2929
}
3030
],
3131
"actions": {
32-
"ids": [
33-
"id1",
34-
"id2"
32+
"docs": [
33+
{
34+
"_index": "my-index-000001",
35+
"_id": "id1"
36+
},
37+
{
38+
"_index": "my-index-000002",
39+
"_id": "id2"
40+
}
3541
]
3642
}
3743
},

x-pack/solutions/search/plugins/search_query_rules/public/components/overview/overview.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 2.0.
66
*/
77

8-
import React from 'react';
8+
import React, { useState } from 'react';
99

1010
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
1111
import {
@@ -25,11 +25,13 @@ import { ErrorPrompt } from '../error_prompt/error_prompt';
2525
import { isPermissionError } from '../../utils/query_rules_utils';
2626
import queryRulesBackground from '../../assets/query-rule-background.svg';
2727
import { QueryRulesSets } from '../query_rules_sets/query_rules_sets';
28+
import { CreateRulesetModal } from '../query_rules_sets/create_ruleset_modal';
29+
2830
import { QueryRulesPageTemplate } from '../../layout/query_rules_page_template';
2931

3032
export const QueryRulesOverview = () => {
3133
const { data: queryRulesData, isInitialLoading, isError, error } = useFetchQueryRulesSets();
32-
34+
const [isCreateModalVisible, setIsCreateModalVisible] = useState(false);
3335
const backgroundProps = css({
3436
backgroundImage: `url(${queryRulesBackground})`,
3537
backgroundSize: 'contain',
@@ -68,12 +70,12 @@ export const QueryRulesOverview = () => {
6870
fill
6971
iconType="plusInCircle"
7072
onClick={() => {
71-
// Logic to create a new query rule set
73+
setIsCreateModalVisible(true);
7274
}}
7375
>
7476
<FormattedMessage
7577
id="xpack.queryRules.queryRulesSetDetail.createButton"
76-
defaultMessage="Create"
78+
defaultMessage="Create ruleset"
7779
/>
7880
</EuiButton>
7981
</EuiFlexItem>
@@ -97,6 +99,13 @@ export const QueryRulesOverview = () => {
9799
: backgroundProps,
98100
}}
99101
>
102+
{isCreateModalVisible && (
103+
<CreateRulesetModal
104+
onClose={() => {
105+
setIsCreateModalVisible(false);
106+
}}
107+
/>
108+
)}
100109
{isInitialLoading && <EuiLoadingSpinner />}
101110
{isError && (
102111
<ErrorPrompt errorType={isPermissionError(error) ? 'missingPermissions' : 'generic'} />
@@ -109,7 +118,7 @@ export const QueryRulesOverview = () => {
109118
<EuiFlexItem>
110119
<EmptyPrompt
111120
getStartedAction={() => {
112-
// Logic to create a new query rule set
121+
setIsCreateModalVisible(true);
113122
}}
114123
/>
115124
</EuiFlexItem>
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import React, { useState } from 'react';
9+
10+
import {
11+
EuiButton,
12+
EuiButtonEmpty,
13+
EuiCheckbox,
14+
EuiFieldText,
15+
EuiForm,
16+
EuiFormRow,
17+
EuiModal,
18+
EuiModalBody,
19+
EuiModalFooter,
20+
EuiModalHeader,
21+
EuiModalHeaderTitle,
22+
EuiSpacer,
23+
useGeneratedHtmlId,
24+
} from '@elastic/eui';
25+
import { FormattedMessage } from '@kbn/i18n-react';
26+
import { i18n } from '@kbn/i18n';
27+
import { formatRulesetName } from '../../utils/query_rules_utils';
28+
import { usePutRuleset } from '../../hooks/use_put_query_rules_ruleset';
29+
interface CreateRulesetModalProps {
30+
onClose: () => void;
31+
}
32+
export const CreateRulesetModal = ({ onClose }: CreateRulesetModalProps) => {
33+
const titleId = useGeneratedHtmlId({ prefix: 'createRulesetModalTitle' });
34+
const formId = useGeneratedHtmlId({ prefix: 'createRulesetModalForm' });
35+
const overwriteId = useGeneratedHtmlId({ prefix: 'createRulesetModalOverwrite' });
36+
37+
const [name, setName] = useState('');
38+
const [rawName, setRawName] = useState('');
39+
const [conflictError, setConflictError] = useState(false);
40+
const [forceWrite, setForceWrite] = useState(false);
41+
const { mutate: createRuleset } = usePutRuleset(
42+
() => {
43+
onClose();
44+
},
45+
() => {
46+
setConflictError(true);
47+
}
48+
);
49+
return (
50+
<EuiModal onClose={onClose}>
51+
<EuiModalHeader>
52+
<EuiModalHeaderTitle id={titleId}>
53+
<FormattedMessage
54+
id="xpack.queryRules.createRulesetModal.title"
55+
defaultMessage="Create ruleset"
56+
/>
57+
</EuiModalHeaderTitle>
58+
</EuiModalHeader>
59+
60+
<EuiModalBody>
61+
<EuiForm
62+
id={formId}
63+
component="form"
64+
onSubmit={(e) => {
65+
e.preventDefault();
66+
createRuleset({ rulesetId: name, forceWrite });
67+
}}
68+
>
69+
<EuiFormRow
70+
fullWidth
71+
label={i18n.translate('xpack.queryRules.createRulesetModal.nameLabel', {
72+
defaultMessage: 'Ruleset ID',
73+
})}
74+
helpText={
75+
!!rawName && !conflictError
76+
? i18n.translate('xpack.queryRules.createRulesetModal.nameHelpText', {
77+
defaultMessage: 'Your ruleset set will be named: {name}',
78+
values: { name },
79+
})
80+
: undefined
81+
}
82+
isInvalid={conflictError}
83+
error={
84+
conflictError
85+
? i18n.translate('xpack.queryRules.createRulesetModal.nameErrorText', {
86+
defaultMessage: 'A ruleset with id {name} already exists.',
87+
values: { name },
88+
})
89+
: undefined
90+
}
91+
>
92+
<EuiFieldText
93+
data-test-subj="searchRulesetCreateRulesetModalFieldText"
94+
value={rawName}
95+
onChange={(e) => {
96+
setRawName(e.target.value);
97+
setName(formatRulesetName(e.target.value));
98+
setConflictError(false);
99+
setForceWrite(false);
100+
}}
101+
/>
102+
</EuiFormRow>
103+
{conflictError && (
104+
<>
105+
<EuiSpacer size="s" />
106+
<EuiFormRow fullWidth>
107+
<EuiCheckbox
108+
id={overwriteId}
109+
data-test-subj="searchRulesetCreateRulesetModalForceWrite"
110+
label={i18n.translate('xpack.queryRules.createRulesetModal.forceWrite', {
111+
defaultMessage: 'Overwrite the existing ruleset.',
112+
})}
113+
checked={forceWrite}
114+
onChange={() => setForceWrite(!forceWrite)}
115+
/>
116+
</EuiFormRow>
117+
</>
118+
)}
119+
</EuiForm>
120+
</EuiModalBody>
121+
122+
<EuiModalFooter>
123+
<EuiButtonEmpty
124+
data-test-subj="searchRulesetCreateRulesetModalCancelButton"
125+
onClick={onClose}
126+
>
127+
<FormattedMessage
128+
id="xpack.queryRules.createRulesetModal.cancelButton"
129+
defaultMessage="Cancel"
130+
/>
131+
</EuiButtonEmpty>
132+
<EuiButton
133+
data-test-subj="searchRulesetCreateRulesetModalCreateButton"
134+
form={formId}
135+
fill
136+
disabled={!name || (conflictError && !forceWrite)}
137+
type="submit"
138+
>
139+
<FormattedMessage
140+
id="xpack.queryRules.createRulesetModal.createButton"
141+
defaultMessage="Create ruleset"
142+
/>
143+
</EuiButton>
144+
</EuiModalFooter>
145+
</EuiModal>
146+
);
147+
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { useMutation, useQueryClient } from '@tanstack/react-query';
9+
import { QueryRulesQueryRuleset } from '@elastic/elasticsearch/lib/api/types';
10+
import { i18n } from '@kbn/i18n';
11+
import { KibanaServerError } from '@kbn/kibana-utils-plugin/common';
12+
import {
13+
QUERY_RULES_QUERY_RULESET_FETCH_KEY,
14+
QUERY_RULES_SETS_QUERY_KEY,
15+
} from '../../common/constants';
16+
import { PLUGIN_ROUTE_ROOT } from '../../common/api_routes';
17+
import { useKibana } from './use_kibana';
18+
19+
interface MutationArgs {
20+
rulesetId: string;
21+
forceWrite?: boolean;
22+
}
23+
24+
export const usePutRuleset = (
25+
onSuccess?: () => void,
26+
onConflictError?: (error: KibanaServerError) => void
27+
) => {
28+
const queryClient = useQueryClient();
29+
const {
30+
services: { http, notifications, application },
31+
} = useKibana();
32+
33+
return useMutation(
34+
async ({ rulesetId, forceWrite }: MutationArgs) => {
35+
return await http.put<QueryRulesQueryRuleset>(
36+
`/internal/search_query_rules/ruleset/${rulesetId}`,
37+
{
38+
query: { forceWrite },
39+
}
40+
);
41+
},
42+
{
43+
onSuccess: (_, { rulesetId }) => {
44+
queryClient.invalidateQueries([QUERY_RULES_QUERY_RULESET_FETCH_KEY]);
45+
queryClient.invalidateQueries([QUERY_RULES_SETS_QUERY_KEY]);
46+
notifications?.toasts?.addSuccess({
47+
title: i18n.translate('xpack.queryRules.putRulesetSuccess', {
48+
defaultMessage: 'Ruleset added',
49+
}),
50+
});
51+
if (onSuccess) {
52+
onSuccess();
53+
}
54+
application.navigateToUrl(
55+
http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}/ruleset/${rulesetId}`)
56+
);
57+
},
58+
onError: (error: { body: KibanaServerError }) => {
59+
if (onConflictError && error.body.statusCode === 409) {
60+
onConflictError(error.body);
61+
} else {
62+
notifications?.toasts?.addError(new Error(error.body.message), {
63+
title: i18n.translate('xpack.queryRules.putRulesetError', {
64+
defaultMessage: 'Error putting ruleset',
65+
}),
66+
toastMessage: error.body.message,
67+
});
68+
}
69+
},
70+
}
71+
);
72+
};

x-pack/solutions/search/plugins/search_query_rules/public/utils/query_rules_utils.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ export const isPermissionError = (error: { body: KibanaServerError }) => {
1414
export const isNotFoundError = (error: { body: KibanaServerError }) => {
1515
return error.body.statusCode === 404;
1616
};
17+
18+
export const formatRulesetName = (rawName: string) =>
19+
rawName
20+
.trim()
21+
.replace(/[^a-zA-Z0-9]+/g, '-') // Replace all special/non-alphanumerical characters with dashes
22+
.replace(/^[-]+|[-]+$/g, '') // Strip all leading and trailing dashes
23+
.toLowerCase();

x-pack/solutions/search/plugins/search_query_rules/server/lib/fetch_query_rules_ruleset.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77

88
import { QueryRulesQueryRuleset } from '@elastic/elasticsearch/lib/api/types';
99
import { ElasticsearchClient } from '@kbn/core/server';
10+
import { isQueryRulesetExist } from './is_query_ruleset_exist';
1011

1112
export const fetchQueryRulesRuleset = async (
1213
client: ElasticsearchClient,
1314
rulesetId: string
14-
): Promise<QueryRulesQueryRuleset> => {
15-
const result = await client.queryRules.getRuleset({
16-
ruleset_id: rulesetId,
17-
});
18-
return result;
15+
): Promise<QueryRulesQueryRuleset | null> => {
16+
if (await isQueryRulesetExist(client, rulesetId)) {
17+
const ruleset = await client.queryRules.getRuleset({
18+
ruleset_id: rulesetId,
19+
});
20+
return ruleset;
21+
}
22+
return null;
1923
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { ElasticsearchClient } from '@kbn/core/server';
9+
10+
export const isQueryRulesetExist = async (
11+
client: ElasticsearchClient,
12+
rulesetId: string
13+
): Promise<boolean> => {
14+
try {
15+
const ruleset = await client.queryRules.getRuleset({
16+
ruleset_id: rulesetId,
17+
});
18+
if (ruleset) {
19+
return true;
20+
}
21+
return false;
22+
} catch (error) {
23+
if (error.meta?.statusCode === 404) return false;
24+
throw error;
25+
}
26+
};

0 commit comments

Comments
 (0)