[ML] Data frame analytics wizard: Only allow data view creation if job will be started (#120042)

* Only allow data view creation if job will be started

* update tests

* no stat fetching when job not started

* ensure result index exists before dataview creation attempt

* update error message and increase retry delay

* use getIdsWithTitle to avoid fieldsWithWildcard call

* move dataview validation to create step

* use exists api in ml index_exists endpoint

* refactor retry function

* fix duplicate i18n ids

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Melissa Alvarez 2021-12-08 01:35:55 -05:00 committed by GitHub
parent bd886e85da
commit 3da312a127
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 290 additions and 242 deletions

View file

@ -7,19 +7,10 @@
import React, { FC, Fragment, useEffect, useMemo, useRef } from 'react';
import { debounce } from 'lodash';
import {
EuiCallOut,
EuiFieldText,
EuiForm,
EuiFormRow,
EuiSpacer,
EuiSwitch,
EuiText,
} from '@elastic/eui';
import { EuiCallOut, EuiFieldText, EuiForm, EuiFormRow, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useMlKibana } from '../../../../../contexts/kibana';
import { CodeEditor } from '../../../../../../../../../../src/plugins/kibana_react/public';
import { useNotifications } from '../../../../../contexts/kibana';
import { ml } from '../../../../../services/ml_api_service';
@ -34,33 +25,15 @@ export const CreateAnalyticsAdvancedEditor: FC<CreateAnalyticsFormProps> = (prop
const { advancedEditorMessages, advancedEditorRawString, isJobCreated } = state;
const {
createIndexPattern,
destinationIndexPatternTitleExists,
jobId,
jobIdEmpty,
jobIdExists,
jobIdValid,
} = state.form;
const { jobId, jobIdEmpty, jobIdExists, jobIdValid } = state.form;
const forceInput = useRef<HTMLInputElement | null>(null);
const { toasts } = useNotifications();
const {
services: {
application: { capabilities },
},
} = useMlKibana();
const onChange = (str: string) => {
setAdvancedEditorRawString(str);
};
const canCreateDataView = useMemo(
() =>
capabilities.savedObjectsManagement.edit === true || capabilities.indexPatterns.save === true,
[capabilities]
);
const debouncedJobIdCheck = useMemo(
() =>
debounce(async () => {
@ -217,47 +190,6 @@ export const CreateAnalyticsAdvancedEditor: FC<CreateAnalyticsFormProps> = (prop
<EuiSpacer />
</Fragment>
))}
{!isJobCreated && (
<Fragment>
<EuiFormRow
isInvalid={
(createIndexPattern && destinationIndexPatternTitleExists) ||
canCreateDataView === false
}
error={[
...(canCreateDataView === false
? [
<EuiText size="xs" color="warning">
{i18n.translate(
'xpack.ml.dataframe.analytics.create.dataViewPermissionWarning',
{
defaultMessage: 'You need permission to create data views.',
}
)}
</EuiText>,
]
: []),
...(createIndexPattern && destinationIndexPatternTitleExists
? [
i18n.translate('xpack.ml.dataframe.analytics.create.dataViewExistsError', {
defaultMessage: 'A data view with this title already exists.',
}),
]
: []),
]}
>
<EuiSwitch
disabled={canCreateDataView === false}
name="mlDataFrameAnalyticsCreateIndexPattern"
label={i18n.translate('xpack.ml.dataframe.analytics.create.createDataViewLabel', {
defaultMessage: 'Create data view',
})}
checked={createIndexPattern === true}
onChange={() => setFormState({ createIndexPattern: !createIndexPattern })}
/>
</EuiFormRow>
</Fragment>
)}
<EuiSpacer />
<CreateStep {...props} step={ANALYTICS_STEPS.CREATE} />
</EuiForm>

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { FC, useState } from 'react';
import React, { FC, useEffect, useMemo, useState } from 'react';
import {
EuiButton,
EuiCheckbox,
@ -13,9 +13,11 @@ import {
EuiFlexItem,
EuiFormRow,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useMlKibana } from '../../../../../contexts/kibana';
import { CreateAnalyticsFormProps } from '../../../analytics_management/hooks/use_create_analytics_form';
import { Messages } from '../shared';
import { ANALYTICS_STEPS } from '../../page';
@ -26,14 +28,38 @@ interface Props extends CreateAnalyticsFormProps {
}
export const CreateStep: FC<Props> = ({ actions, state, step }) => {
const { createAnalyticsJob, startAnalyticsJob } = actions;
const { isAdvancedEditorValidJson, isJobCreated, isJobStarted, isValid, requestMessages } = state;
const { jobId, jobType } = state.form;
const {
services: {
application: { capabilities },
},
} = useMlKibana();
const [checked, setChecked] = useState<boolean>(true);
const canCreateDataView = useMemo(
() =>
capabilities.savedObjectsManagement.edit === true || capabilities.indexPatterns.save === true,
[capabilities]
);
const { createAnalyticsJob, setFormState, startAnalyticsJob } = actions;
const { isAdvancedEditorValidJson, isJobCreated, isJobStarted, isValid, requestMessages } = state;
const {
createIndexPattern,
destinationIndex,
destinationIndexPatternTitleExists,
jobId,
jobType,
} = state.form;
const [startChecked, setStartChecked] = useState<boolean>(true);
const [creationTriggered, setCreationTriggered] = useState<boolean>(false);
const [showProgress, setShowProgress] = useState<boolean>(false);
useEffect(() => {
if (canCreateDataView === false) {
setFormState({ createIndexPattern: false });
}
}, [capabilities]);
if (step !== ANALYTICS_STEPS.CREATE) return null;
const handleCreation = async () => {
@ -44,7 +70,7 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
setCreationTriggered(false);
}
if (checked && creationSuccess === true) {
if (startChecked && creationSuccess === true) {
setShowProgress(true);
startAnalyticsJob();
}
@ -53,32 +79,114 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
return (
<div data-test-subj="mlAnalyticsCreateJobWizardCreateStep active">
{!isJobCreated && !isJobStarted && (
<EuiFlexGroup gutterSize="s">
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexItem grow={false}>
<EuiFormRow
helpText={i18n.translate(
'xpack.ml.dataframe.analytics.create.startCheckboxHelpText',
{
defaultMessage:
'If unselected, job can be started later by returning to the jobs list.',
}
)}
>
<EuiCheckbox
data-test-subj="mlAnalyticsCreateJobWizardStartJobCheckbox"
id={'dataframe-create-start-checkbox'}
label={i18n.translate('xpack.ml.dataframe.analytics.create.wizardStartCheckbox', {
defaultMessage: 'Start immediately',
})}
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>
</EuiFormRow>
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiFormRow
helpText={i18n.translate(
'xpack.ml.dataframe.analytics.create.startCheckboxHelpText',
{
defaultMessage:
'If unselected, job can be started later by returning to the jobs list.',
}
)}
>
<EuiCheckbox
data-test-subj="mlAnalyticsCreateJobWizardStartJobCheckbox"
id={'dataframe-create-start-checkbox'}
label={i18n.translate(
'xpack.ml.dataframe.analytics.create.wizardStartCheckbox',
{
defaultMessage: 'Start immediately',
}
)}
checked={startChecked}
onChange={(e) => {
setStartChecked(e.target.checked);
if (e.target.checked === false) {
setFormState({ createIndexPattern: false });
}
}}
/>
</EuiFormRow>
</EuiFlexItem>
{startChecked ? (
<EuiFlexItem grow={false}>
<EuiFormRow
fullWidth
isInvalid={
(createIndexPattern && destinationIndexPatternTitleExists) ||
createIndexPattern === false ||
canCreateDataView === false
}
error={[
...(canCreateDataView === false
? [
<EuiText size="xs" color="warning">
{i18n.translate(
'xpack.ml.dataframe.analytics.create.dataViewPermissionWarning',
{
defaultMessage: 'You need permission to create data views.',
}
)}
</EuiText>,
]
: []),
...(createIndexPattern && destinationIndexPatternTitleExists
? [
i18n.translate(
'xpack.ml.dataframe.analytics.create.dataViewExistsError',
{
defaultMessage:
'A data view with the title {title} already exists.',
values: { title: destinationIndex },
}
),
]
: []),
...(!createIndexPattern && !destinationIndexPatternTitleExists
? [
<EuiText size="xs" color="warning">
{i18n.translate(
'xpack.ml.dataframe.analytics.create.shouldCreateDataViewMessage',
{
defaultMessage:
'You may not be able to view job results if a data view is not created for the destination index.',
}
)}
</EuiText>,
]
: []),
]}
>
<EuiCheckbox
disabled={isJobCreated || canCreateDataView === false}
name="mlDataFrameAnalyticsCreateIndexPattern"
id={'dataframe-create-data-view-checkbox'}
label={i18n.translate(
'xpack.ml.dataframe.analytics.create.createDataViewLabel',
{
defaultMessage: 'Create data view',
}
)}
checked={createIndexPattern === true}
onChange={() => setFormState({ createIndexPattern: !createIndexPattern })}
data-test-subj="mlAnalyticsCreateJobWizardCreateIndexPatternCheckbox"
/>
</EuiFormRow>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
className="mlAnalyticsCreateWizard__footerButton"
disabled={!isValid || !isAdvancedEditorValidJson}
disabled={
!isValid ||
!isAdvancedEditorValidJson ||
(destinationIndexPatternTitleExists === true && createIndexPattern === true)
}
onClick={handleCreation}
fill
isLoading={creationTriggered}
@ -93,9 +201,9 @@ export const CreateStep: FC<Props> = ({ actions, state, step }) => {
)}
<EuiSpacer size="s" />
<Messages messages={requestMessages} />
{isJobCreated === true && (
{isJobCreated === true ? (
<CreateStepFooter jobId={jobId} jobType={jobType!} showProgress={showProgress} />
)}
) : null}
</div>
);
};

View file

@ -54,6 +54,8 @@ export const CreateStepFooter: FC<Props> = ({ jobId, jobType, showProgress }) =>
}, []);
useEffect(() => {
if (showProgress === false) return;
const interval = setInterval(async () => {
try {
const analyticsStats = await ml.dataFrameAnalytics.getDataFrameAnalyticsStats(jobId);
@ -129,11 +131,11 @@ export const CreateStepFooter: FC<Props> = ({ jobId, jobType, showProgress }) =>
<EuiFlexItem grow={false}>
<BackToListPanel />
</EuiFlexItem>
{jobFinished === true && (
{jobFinished === true ? (
<EuiFlexItem grow={false}>
<ViewResultsPanel jobId={jobId} analysisType={jobType} />
</EuiFlexItem>
)}
) : null}
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>

View file

@ -7,15 +7,7 @@
import React, { FC, Fragment, useRef, useEffect, useMemo, useState } from 'react';
import { debounce } from 'lodash';
import {
EuiFieldText,
EuiFormRow,
EuiLink,
EuiSpacer,
EuiSwitch,
EuiText,
EuiTextArea,
} from '@elastic/eui';
import { EuiFieldText, EuiFormRow, EuiLink, EuiSpacer, EuiSwitch, EuiTextArea } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useMlKibana } from '../../../../../contexts/kibana';
@ -42,23 +34,17 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
setCurrentStep,
}) => {
const {
services: {
docLinks,
notifications,
application: { capabilities },
},
services: { docLinks, notifications },
} = useMlKibana();
const createIndexLink = docLinks.links.apis.createIndex;
const { setFormState } = actions;
const { form, cloneJob, hasSwitchedToEditor, isJobCreated } = state;
const {
createIndexPattern,
description,
destinationIndex,
destinationIndexNameEmpty,
destinationIndexNameExists,
destinationIndexNameValid,
destinationIndexPatternTitleExists,
jobId,
jobIdEmpty,
jobIdExists,
@ -75,11 +61,6 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
(cloneJob !== undefined && resultsField === DEFAULT_RESULTS_FIELD)
);
const canCreateDataView = useMemo(
() =>
capabilities.savedObjectsManagement.edit === true || capabilities.indexPatterns.save === true,
[capabilities]
);
const forceInput = useRef<HTMLInputElement | null>(null);
const isStepInvalid =
@ -87,8 +68,7 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
jobIdExists === true ||
jobIdValid === false ||
destinationIndexNameEmpty === true ||
destinationIndexNameValid === false ||
(destinationIndexPatternTitleExists === true && createIndexPattern === true);
destinationIndexNameValid === false;
const debouncedIndexCheck = debounce(async () => {
try {
@ -158,12 +138,6 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
}
}, [destIndexSameAsId, jobId]);
useEffect(() => {
if (canCreateDataView === false) {
setFormState({ createIndexPattern: false });
}
}, [capabilities]);
return (
<Fragment>
<EuiFormRow
@ -359,56 +333,6 @@ export const DetailsStepForm: FC<CreateAnalyticsStepProps> = ({
/>
</EuiFormRow>
)}
<EuiFormRow
fullWidth
isInvalid={
(createIndexPattern && destinationIndexPatternTitleExists) ||
createIndexPattern === false ||
canCreateDataView === false
}
error={[
...(canCreateDataView === false
? [
<EuiText size="xs" color="warning">
{i18n.translate('xpack.ml.dataframe.analytics.create.dataViewPermissionWarning', {
defaultMessage: 'You need permission to create data views.',
})}
</EuiText>,
]
: []),
...(createIndexPattern && destinationIndexPatternTitleExists
? [
i18n.translate('xpack.ml.dataframe.analytics.create.dataViewExistsError', {
defaultMessage: 'A data view with this title already exists.',
}),
]
: []),
...(!createIndexPattern
? [
<EuiText size="xs" color="warning">
{i18n.translate(
'xpack.ml.dataframe.analytics.create.shouldCreateDataViewMessage',
{
defaultMessage:
'You may not be able to view job results if a data view is not created for the destination index.',
}
)}
</EuiText>,
]
: []),
]}
>
<EuiSwitch
disabled={isJobCreated === true || canCreateDataView === false}
name="mlDataFrameAnalyticsCreateIndexPattern"
label={i18n.translate('xpack.ml.dataframe.analytics.create.createDataViewLabel', {
defaultMessage: 'Create data view',
})}
checked={createIndexPattern === true}
onChange={() => setFormState({ createIndexPattern: !createIndexPattern })}
data-test-subj="mlAnalyticsCreateJobWizardCreateIndexPatternSwitch"
/>
</EuiFormRow>
<EuiSpacer />
<ContinueButton
isDisabled={isStepInvalid}

View file

@ -57,7 +57,7 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {
const checkIndexPatternExists = async () => {
try {
const dv = (await dataViews.find(indexName)).find(({ title }) => title === indexName);
const dv = (await dataViews.getIdsWithTitle()).find(({ title }) => title === indexName);
if (dv !== undefined) {
setIndexPatternExists(true);
} else {

View file

@ -47,6 +47,49 @@ export interface CreateAnalyticsStepProps extends CreateAnalyticsFormProps {
stepActivated?: boolean;
}
async function checkIndexExists(destinationIndex: string) {
let resp;
let errorMessage;
try {
resp = await ml.checkIndicesExists({ indices: [destinationIndex] });
} catch (e) {
errorMessage = extractErrorMessage(e);
}
return { resp, errorMessage };
}
async function retryIndexExistsCheck(
destinationIndex: string
): Promise<{ success: boolean; indexExists: boolean; errorMessage?: string }> {
let retryCount = 15;
let resp = await checkIndexExists(destinationIndex);
let indexExists = resp.resp && resp.resp[destinationIndex] && resp.resp[destinationIndex].exists;
while (retryCount > 1 && !indexExists) {
retryCount--;
await delay(1000);
resp = await checkIndexExists(destinationIndex);
indexExists = resp.resp && resp.resp[destinationIndex] && resp.resp[destinationIndex].exists;
}
if (indexExists) {
return { success: true, indexExists: true };
}
return {
success: false,
indexExists: false,
...(resp.errorMessage !== undefined ? { errorMessage: resp.errorMessage } : {}),
};
}
function delay(ms = 1000) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
const mlContext = useMlContext();
const [state, dispatch] = useReducer(reducer, getInitialState());
@ -125,49 +168,88 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
const createKibanaIndexPattern = async () => {
const dataViewName = destinationIndex;
try {
await mlContext.dataViewsContract.createAndSave(
{
title: dataViewName,
},
false,
true
);
addRequestMessage({
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.createDataViewSuccessMessage',
{
defaultMessage: 'Kibana data view {dataViewName} created.',
values: { dataViewName },
const exists = await retryIndexExistsCheck(destinationIndex);
if (exists?.success === true) {
// index exists - create data view
if (exists?.indexExists === true) {
try {
await mlContext.dataViewsContract.createAndSave(
{
title: dataViewName,
},
false,
true
);
addRequestMessage({
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.createDataViewSuccessMessage',
{
defaultMessage: 'Kibana data view {dataViewName} created.',
values: { dataViewName },
}
),
});
} catch (e) {
// handle data view creation error
if (e instanceof DuplicateDataViewError) {
addRequestMessage({
error: i18n.translate(
'xpack.ml.dataframe.analytics.create.duplicateDataViewErrorMessageError',
{
defaultMessage: 'The data view {dataViewName} already exists.',
values: { dataViewName },
}
),
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.duplicateDataViewErrorMessage',
{
defaultMessage: 'An error occurred creating the Kibana data view:',
}
),
});
} else {
addRequestMessage({
error: extractErrorMessage(e),
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.createDataViewErrorMessage',
{
defaultMessage: 'An error occurred creating the Kibana data view:',
}
),
});
}
),
});
} catch (e) {
if (e instanceof DuplicateDataViewError) {
}
}
} else {
// Ran out of retries or there was a problem checking index exists
if (exists?.errorMessage) {
addRequestMessage({
error: i18n.translate(
'xpack.ml.dataframe.analytics.create.duplicateDataViewErrorMessageError',
'xpack.ml.dataframe.analytics.create.errorCheckingDestinationIndexDataFrameAnalyticsJob',
{
defaultMessage: 'The data view {dataViewName} already exists.',
values: { dataViewName },
defaultMessage: '{errorMessage}',
values: { errorMessage: exists.errorMessage },
}
),
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.duplicateDataViewErrorMessage',
'xpack.ml.dataframe.analytics.create.errorOccurredCheckingDestinationIndexDataFrameAnalyticsJob',
{
defaultMessage: 'An error occurred creating the Kibana data view:',
defaultMessage: 'An error occurred checking destination index exists.',
}
),
});
} else {
addRequestMessage({
error: extractErrorMessage(e),
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.createDataViewErrorMessage',
error: i18n.translate(
'xpack.ml.dataframe.analytics.create.destinationIndexNotCreatedForDataFrameAnalyticsJob',
{
defaultMessage: 'An error occurred creating the Kibana data view:',
defaultMessage: 'Destination index has not yet been created.',
}
),
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.unableToCreateDataViewForDataFrameAnalyticsJob',
{
defaultMessage: 'Unable to create data view.',
}
),
});

View file

@ -118,6 +118,7 @@
"MlInfo",
"MlEsSearch",
"MlIndexExists",
"MlSpecificIndexExists",
"JobAuditMessages",
"GetJobAuditMessages",

View file

@ -225,17 +225,16 @@ export function systemRoutes(
try {
const { indices } = request.body;
const options = {
index: indices,
fields: ['*'],
ignore_unavailable: true,
allow_no_indices: true,
};
const results = await Promise.all(
indices.map(async (index) =>
client.asCurrentUser.indices.exists({
index,
})
)
);
const { body } = await client.asCurrentUser.fieldCaps(options);
const result = indices.reduce((acc, cur) => {
acc[cur] = { exists: body.indices.includes(cur) };
const result = indices.reduce((acc, cur, i) => {
acc[cur] = { exists: results[i].body };
return acc;
}, {} as Record<string, { exists: boolean }>);

View file

@ -195,12 +195,6 @@ export default function ({ getService }: FtrProviderContext) {
await ml.dataFrameAnalyticsCreation.assertDestIndexInputExists();
await ml.dataFrameAnalyticsCreation.setDestIndex(testData.destinationIndex);
await ml.testExecution.logTestStep('sets the create data view switch');
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
await ml.testExecution.logTestStep('continues to the validation step');
await ml.dataFrameAnalyticsCreation.continueToValidationStep();
@ -215,6 +209,12 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('continues to the create step');
await ml.dataFrameAnalyticsCreation.continueToCreateStep();
await ml.testExecution.logTestStep('sets the create data view switch');
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
});
it('runs the analytics job and displays it correctly in the job list', async () => {

View file

@ -217,12 +217,6 @@ export default function ({ getService }: FtrProviderContext) {
await ml.dataFrameAnalyticsCreation.assertDestIndexInputExists();
await ml.dataFrameAnalyticsCreation.setDestIndex(testData.destinationIndex);
await ml.testExecution.logTestStep('sets the create data view switch');
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
await ml.testExecution.logTestStep('continues to the validation step');
await ml.dataFrameAnalyticsCreation.continueToValidationStep();
@ -232,6 +226,12 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('continues to the create step');
await ml.dataFrameAnalyticsCreation.continueToCreateStep();
await ml.testExecution.logTestStep('sets the create data view switch');
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
});
it('runs the analytics job and displays it correctly in the job list', async () => {

View file

@ -189,12 +189,6 @@ export default function ({ getService }: FtrProviderContext) {
await ml.dataFrameAnalyticsCreation.assertDestIndexInputExists();
await ml.dataFrameAnalyticsCreation.setDestIndex(testData.destinationIndex);
await ml.testExecution.logTestStep('sets the create data view switch');
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
await ml.testExecution.logTestStep('continues to the validation step');
await ml.dataFrameAnalyticsCreation.continueToValidationStep();
@ -204,6 +198,12 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testExecution.logTestStep('continues to the create step');
await ml.dataFrameAnalyticsCreation.continueToCreateStep();
await ml.testExecution.logTestStep('sets the create data view switch');
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
});
it('runs the analytics job and displays it correctly in the job list', async () => {

View file

@ -532,15 +532,15 @@ export function MachineLearningDataFrameAnalyticsCreationProvider(
},
async assertCreateIndexPatternSwitchExists() {
await testSubjects.existOrFail(`mlAnalyticsCreateJobWizardCreateIndexPatternSwitch`, {
await testSubjects.existOrFail(`mlAnalyticsCreateJobWizardCreateIndexPatternCheckbox`, {
allowHidden: true,
});
},
async getCreateIndexPatternSwitchCheckState(): Promise<boolean> {
const state = await testSubjects.getAttribute(
'mlAnalyticsCreateJobWizardCreateIndexPatternSwitch',
'aria-checked'
'mlAnalyticsCreateJobWizardCreateIndexPatternCheckbox',
'checked'
);
return state === 'true';
},
@ -584,7 +584,7 @@ export function MachineLearningDataFrameAnalyticsCreationProvider(
async setCreateIndexPatternSwitchState(checkState: boolean) {
if ((await this.getCreateIndexPatternSwitchCheckState()) !== checkState) {
await testSubjects.click('mlAnalyticsCreateJobWizardCreateIndexPatternSwitch');
await testSubjects.click('mlAnalyticsCreateJobWizardCreateIndexPatternCheckbox');
}
await this.assertCreateIndexPatternSwitchCheckState(checkState);
},