Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Logs UI] Add missing ML capabilities checks #72606

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@

export * from './log_analysis_job_problem_indicator';
export * from './notices_section';
export * from './recreate_job_button';
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import React from 'react';
import { RecreateJobCallout } from './recreate_job_callout';

export const JobConfigurationOutdatedCallout: React.FC<{
hasSetupCapabilities: boolean;
moduleName: string;
onRecreateMlJob: () => void;
}> = ({ moduleName, onRecreateMlJob }) => (
}> = ({ hasSetupCapabilities, moduleName, onRecreateMlJob }) => (
<RecreateJobCallout
hasSetupCapabilities={hasSetupCapabilities}
title={i18n.translate('xpack.infra.logs.analysis.jobConfigurationOutdatedCalloutTitle', {
defaultMessage: 'The {moduleName} ML job configuration is outdated',
values: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import React from 'react';
import { RecreateJobCallout } from './recreate_job_callout';

export const JobDefinitionOutdatedCallout: React.FC<{
hasSetupCapabilities: boolean;
moduleName: string;
onRecreateMlJob: () => void;
}> = ({ moduleName, onRecreateMlJob }) => (
}> = ({ hasSetupCapabilities, moduleName, onRecreateMlJob }) => (
<RecreateJobCallout
hasSetupCapabilities={hasSetupCapabilities}
title={i18n.translate('xpack.infra.logs.analysis.jobDefinitionOutdatedCalloutTitle', {
defaultMessage: 'The {moduleName} ML job definition is outdated',
values: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { FirstUseCallout } from '../log_analysis_results';
export const LogAnalysisJobProblemIndicator: React.FC<{
hasOutdatedJobConfigurations: boolean;
hasOutdatedJobDefinitions: boolean;
hasSetupCapabilities: boolean;
hasStoppedJobs: boolean;
isFirstUse: boolean;
moduleName: string;
Expand All @@ -22,6 +23,7 @@ export const LogAnalysisJobProblemIndicator: React.FC<{
}> = ({
hasOutdatedJobConfigurations,
hasOutdatedJobDefinitions,
hasSetupCapabilities,
hasStoppedJobs,
isFirstUse,
moduleName,
Expand All @@ -32,12 +34,14 @@ export const LogAnalysisJobProblemIndicator: React.FC<{
<>
{hasOutdatedJobDefinitions ? (
<JobDefinitionOutdatedCallout
hasSetupCapabilities={hasSetupCapabilities}
moduleName={moduleName}
onRecreateMlJob={onRecreateMlJobForUpdate}
/>
) : null}
{hasOutdatedJobConfigurations ? (
<JobConfigurationOutdatedCallout
hasSetupCapabilities={hasSetupCapabilities}
moduleName={moduleName}
onRecreateMlJob={onRecreateMlJobForReconfiguration}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { CategoryQualityWarnings } from './quality_warning_notices';
export const CategoryJobNoticesSection: React.FC<{
hasOutdatedJobConfigurations: boolean;
hasOutdatedJobDefinitions: boolean;
hasSetupCapabilities: boolean;
hasStoppedJobs: boolean;
isFirstUse: boolean;
moduleName: string;
Expand All @@ -21,6 +22,7 @@ export const CategoryJobNoticesSection: React.FC<{
}> = ({
hasOutdatedJobConfigurations,
hasOutdatedJobDefinitions,
hasSetupCapabilities,
hasStoppedJobs,
isFirstUse,
moduleName,
Expand All @@ -32,6 +34,7 @@ export const CategoryJobNoticesSection: React.FC<{
<LogAnalysisJobProblemIndicator
hasOutdatedJobConfigurations={hasOutdatedJobConfigurations}
hasOutdatedJobDefinitions={hasOutdatedJobDefinitions}
hasSetupCapabilities={hasSetupCapabilities}
hasStoppedJobs={hasStoppedJobs}
isFirstUse={isFirstUse}
moduleName={moduleName}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { EuiCallOut } from '@elastic/eui';

import { RecreateJobButton } from './recreate_job_button';
import React from 'react';
import { RecreateJobButton } from '../log_analysis_setup/create_job_button';

export const RecreateJobCallout: React.FC<{
hasSetupCapabilities?: boolean;
onRecreateMlJob: () => void;
title?: React.ReactNode;
}> = ({ children, onRecreateMlJob, title }) => (
}> = ({ children, hasSetupCapabilities, onRecreateMlJob, title }) => (
<EuiCallOut color="warning" iconType="alert" title={title}>
<p>{children}</p>
<RecreateJobButton color="warning" onClick={onRecreateMlJob} />
<RecreateJobButton
color="warning"
hasSetupCapabilities={hasSetupCapabilities}
onClick={onRecreateMlJob}
/>
</EuiCallOut>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiButton, PropsOf } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import { MissingSetupPrivilegesToolTip } from './missing_setup_privileges_tooltip';

export const CreateJobButton: React.FunctionComponent<
{
hasSetupCapabilities?: boolean;
} & PropsOf<typeof EuiButton>
> = ({ hasSetupCapabilities = true, children, ...buttonProps }) => {
const button = (
<EuiButton isDisabled={!hasSetupCapabilities} {...buttonProps}>
{children ?? (
<FormattedMessage
id="xpack.infra.logs.analysis.createJobButtonLabel"
defaultMessage="Create ML jobs"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the default text here should it be job instead of jobs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say, it depends on whether we want to abstract away the fact that this module happens to only contain one job. 🤷

/>
)}
</EuiButton>
);

return hasSetupCapabilities ? (
button
) : (
<MissingSetupPrivilegesToolTip position="bottom" delay="regular">
{button}
</MissingSetupPrivilegesToolTip>
);
};

export const RecreateJobButton: React.FunctionComponent<PropsOf<typeof CreateJobButton>> = ({
children,
...otherProps
}) => (
<CreateJobButton {...otherProps}>
{children ?? (
<FormattedMessage
id="xpack.infra.logs.analysis.recreateJobButtonLabel"
defaultMessage="Recreate ML job"
/>
)}
</CreateJobButton>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';

export const missingMlPrivilegesTitle = i18n.translate(
'xpack.infra.logs.analysis.missingMlPrivilegesTitle',
{
defaultMessage: 'Additional Machine Learning privileges required',
}
);

export const missingMlResultsPrivilegesDescription = i18n.translate(
'xpack.infra.logs.analysis.missingMlResultsPrivilegesDescription',
{
defaultMessage:
'This feature makes use of Machine Learning jobs, which require at least the read permission for the Machine Learning app in order to access their status and results.',
}
);

export const missingMlSetupPrivilegesDescription = i18n.translate(
'xpack.infra.logs.analysis.missingMlSetupPrivilegesDescription',
{
defaultMessage:
'This feature makes use of Machine Learning jobs, which require all permissions for the Machine Learning app in order to be set up.',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiEmptyPrompt, EuiCode } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiEmptyPrompt } from '@elastic/eui';
import React from 'react';

import { euiStyled } from '../../../../../observability/public';
import {
missingMlPrivilegesTitle,
missingMlResultsPrivilegesDescription,
} from './missing_privileges_messages';
import { UserManagementLink } from './user_management_link';

export const MissingResultsPrivilegesPrompt: React.FunctionComponent = () => (
<EmptyPrompt
title={
<h2>
<FormattedMessage
id="xpack.infra.logs.analysis.missingMlResultsPrivilegesTitle"
defaultMessage="Additional Machine Learning privileges required"
/>
</h2>
}
body={
<p>
<FormattedMessage
id="xpack.infra.logs.analysis.missingMlResultsPrivilegesBody"
defaultMessage="This feature makes use of Machine Learning jobs, which require at least the {machineLearningUserRole} role in order to access their status and results."
values={{
machineLearningUserRole: <EuiCode>machine_learning_user</EuiCode>,
}}
/>
</p>
}
title={<h2>{missingMlPrivilegesTitle}</h2>}
body={<p>{missingMlResultsPrivilegesDescription}</p>}
actions={<UserManagementLink />}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiEmptyPrompt, EuiCode } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiEmptyPrompt } from '@elastic/eui';
import React from 'react';

import { euiStyled } from '../../../../../observability/public';
import {
missingMlPrivilegesTitle,
missingMlSetupPrivilegesDescription,
} from './missing_privileges_messages';
import { UserManagementLink } from './user_management_link';

export const MissingSetupPrivilegesPrompt: React.FunctionComponent = () => (
<EmptyPrompt
title={
<h2>
<FormattedMessage
id="xpack.infra.logs.analysis.missingMlSetupPrivilegesTitle"
defaultMessage="Additional Machine Learning privileges required"
/>
</h2>
}
body={
<p>
<FormattedMessage
id="xpack.infra.logs.analysis.missingMlSetupPrivilegesBody"
defaultMessage="This feature makes use of Machine Learning jobs, which require the {machineLearningAdminRole} role in order to be set up."
values={{
machineLearningAdminRole: <EuiCode>machine_learning_admin</EuiCode>,
}}
/>
</p>
}
title={<h2>{missingMlPrivilegesTitle}</h2>}
body={<p>{missingMlSetupPrivilegesDescription}</p>}
actions={<UserManagementLink />}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiToolTip, PropsOf } from '@elastic/eui';
import React from 'react';
import {
missingMlPrivilegesTitle,
missingMlSetupPrivilegesDescription,
} from './missing_privileges_messages';

export const MissingSetupPrivilegesToolTip: React.FC<Omit<
PropsOf<EuiToolTip>,
'content' | 'title'
>> = (props) => (
<EuiToolTip
{...props}
content={missingMlSetupPrivilegesDescription}
title={missingMlPrivilegesTitle}
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useCallback } from 'react';
import { useLogAnalysisCapabilitiesContext } from '../../../../containers/logs/log_analysis';
import {
logEntryCategoriesModule,
useLogEntryCategoriesModuleContext,
Expand All @@ -20,6 +21,7 @@ import type { ModuleId } from './setup_flyout_state';
export const LogAnalysisModuleList: React.FC<{
onViewModuleSetup: (module: ModuleId) => void;
}> = ({ onViewModuleSetup }) => {
const { hasLogAnalysisSetupCapabilities } = useLogAnalysisCapabilitiesContext();
const { setupStatus: logEntryRateSetupStatus } = useLogEntryRateModuleContext();
const { setupStatus: logEntryCategoriesSetupStatus } = useLogEntryCategoriesModuleContext();

Expand All @@ -35,6 +37,7 @@ export const LogAnalysisModuleList: React.FC<{
<EuiFlexGroup>
<EuiFlexItem>
<LogAnalysisModuleListCard
hasSetupCapabilities={hasLogAnalysisSetupCapabilities}
moduleDescription={logEntryRateModule.moduleDescription}
moduleName={logEntryRateModule.moduleName}
moduleStatus={logEntryRateSetupStatus}
Expand All @@ -43,6 +46,7 @@ export const LogAnalysisModuleList: React.FC<{
</EuiFlexItem>
<EuiFlexItem>
<LogAnalysisModuleListCard
hasSetupCapabilities={hasLogAnalysisSetupCapabilities}
moduleDescription={logEntryCategoriesModule.moduleDescription}
moduleName={logEntryCategoriesModule.moduleName}
moduleStatus={logEntryCategoriesSetupStatus}
Expand Down
Loading