mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
Add link to ingest pipeline dashboard from Stack Monitoring (#149721)
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Closes https://github.com/elastic/kibana/issues/149386
This commit is contained in:
parent
f2b8c7f907
commit
136171a63d
6 changed files with 200 additions and 4 deletions
|
@ -16,7 +16,9 @@
|
|||
"triggersActionsUi",
|
||||
"alerting",
|
||||
"actions",
|
||||
"encryptedSavedObjects"
|
||||
"encryptedSavedObjects",
|
||||
"dashboard",
|
||||
"fleet"
|
||||
],
|
||||
"server": true,
|
||||
"ui": true,
|
||||
|
|
|
@ -6,10 +6,15 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { includes } from 'lodash';
|
||||
import { DashboardStart } from '@kbn/dashboard-plugin/public';
|
||||
import { FleetStart } from '@kbn/fleet-plugin/public';
|
||||
import { EuiIcon, EuiToolTip } from '@elastic/eui';
|
||||
import { PageTemplate } from '../page_template';
|
||||
import { TabMenuItem, PageTemplateProps } from '../page_template';
|
||||
import { ML_SUPPORTED_LICENSES } from '../../../../common/constants';
|
||||
import { ingestPipelineTabOnClick } from './ingest_pipeline_modal';
|
||||
|
||||
interface ElasticsearchTemplateProps extends PageTemplateProps {
|
||||
cluster?: any;
|
||||
|
@ -19,6 +24,8 @@ export const ElasticsearchTemplate: React.FC<ElasticsearchTemplateProps> = ({
|
|||
cluster,
|
||||
...props
|
||||
}) => {
|
||||
const { services } = useKibana<{ dashboard?: DashboardStart; fleet?: FleetStart }>();
|
||||
|
||||
const tabs: TabMenuItem[] = [
|
||||
{
|
||||
id: 'overview',
|
||||
|
@ -43,6 +50,25 @@ export const ElasticsearchTemplate: React.FC<ElasticsearchTemplateProps> = ({
|
|||
},
|
||||
];
|
||||
|
||||
if (services.dashboard) {
|
||||
tabs.push({
|
||||
id: 'ingest_pipeines',
|
||||
label: i18n.translate('xpack.monitoring.esNavigation.ingestPipelinesLinkText', {
|
||||
defaultMessage: 'Ingest Pipelines',
|
||||
}),
|
||||
prepend: (
|
||||
<EuiToolTip
|
||||
content={i18n.translate('xpack.monitoring.esNavigation.ingestPipelinesBetaTooltip', {
|
||||
defaultMessage: 'Ingest Pipeline monitoring is a beta feature',
|
||||
})}
|
||||
>
|
||||
<EuiIcon type="beaker" />
|
||||
</EuiToolTip>
|
||||
),
|
||||
onClick: () => ingestPipelineTabOnClick(services),
|
||||
});
|
||||
}
|
||||
|
||||
if (cluster && mlIsSupported(cluster.license)) {
|
||||
tabs.push({
|
||||
id: 'ml',
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import type { CoreStart } from '@kbn/core/public';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiCallOut, EuiConfirmModal, EuiSpacer } from '@elastic/eui';
|
||||
import { DashboardStart } from '@kbn/dashboard-plugin/public';
|
||||
import { FleetStart } from '@kbn/fleet-plugin/public';
|
||||
|
||||
const INGEST_PIPELINE_DASHBOARD_ID = 'elasticsearch-metrics-ingest-pipelines';
|
||||
|
||||
/**
|
||||
* If the ingest pipeline dashboard is installed, navigate to it. Otherwise, prompt the user to install the package
|
||||
* first, then navigate. If user does not have permission to install packages, show a message.
|
||||
* @param services
|
||||
* @returns
|
||||
*/
|
||||
export const ingestPipelineTabOnClick = async (
|
||||
services: Partial<CoreStart & { dashboard: DashboardStart; fleet: FleetStart }>
|
||||
) => {
|
||||
const dashboard = await services.savedObjects!.client.get(
|
||||
'dashboard',
|
||||
INGEST_PIPELINE_DASHBOARD_ID
|
||||
);
|
||||
const dashboardFound = !dashboard.error && dashboard.attributes;
|
||||
|
||||
const navigateToDashboard = () =>
|
||||
services.dashboard!.locator!.navigate({
|
||||
dashboardId: INGEST_PIPELINE_DASHBOARD_ID,
|
||||
});
|
||||
|
||||
if (!dashboardFound) {
|
||||
const installPackage = () => services.http!.post('/api/fleet/epm/packages/elasticsearch');
|
||||
|
||||
const ref = services.overlays!.openModal(
|
||||
toMountPoint(
|
||||
<IngestPipelineModal
|
||||
installPackage={installPackage}
|
||||
navigateToDashboard={navigateToDashboard}
|
||||
canInstallPackages={!!services.fleet?.authz.integrations.installPackages}
|
||||
closeModal={() => ref.close()}
|
||||
/>,
|
||||
{
|
||||
theme$: services.theme?.theme$,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return await ref.onClose;
|
||||
} else {
|
||||
return navigateToDashboard();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Modal to prompt the user to either install the Elasticsearch integration or contact an admin.
|
||||
*/
|
||||
export const IngestPipelineModal = ({
|
||||
canInstallPackages,
|
||||
closeModal,
|
||||
installPackage,
|
||||
navigateToDashboard,
|
||||
}: {
|
||||
closeModal: () => void;
|
||||
canInstallPackages: boolean;
|
||||
installPackage: () => Promise<unknown>;
|
||||
navigateToDashboard: () => void;
|
||||
}) => {
|
||||
const [installing, setInstalling] = useState(false);
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
if (!canInstallPackages) {
|
||||
return (
|
||||
<EuiConfirmModal
|
||||
title={i18n.translate(
|
||||
'xpack.monitoring.esNavigation.ingestPipelineModal.noPermissionToInstallPackage.packageRequiredTitle',
|
||||
{ defaultMessage: 'Elasticsearch integration is required' }
|
||||
)}
|
||||
confirmButtonText={i18n.translate(
|
||||
'xpack.monitoring.esNavigation.ingestPipelineModal.noPermissionToInstallPackage.confirmButtonText',
|
||||
{ defaultMessage: 'OK' }
|
||||
)}
|
||||
onCancel={closeModal}
|
||||
onConfirm={closeModal}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.esNavigation.ingestPipelineModal.noPermissionToInstallPackage.descriptionText"
|
||||
defaultMessage="Viewing Ingest pipeline metrics requires installing the Elasticsearch integration. You must ask your administrator to install it."
|
||||
/>
|
||||
</p>
|
||||
</EuiConfirmModal>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiConfirmModal
|
||||
title={i18n.translate(
|
||||
'xpack.monitoring.esNavigation.ingestPipelineModal.installPromptTitle',
|
||||
{
|
||||
defaultMessage: 'Install Elasticsearch integration?',
|
||||
}
|
||||
)}
|
||||
confirmButtonText={i18n.translate(
|
||||
'xpack.monitoring.esNavigation.ingestPipelineModal.installButtonText',
|
||||
{ defaultMessage: 'Install' }
|
||||
)}
|
||||
cancelButtonText={i18n.translate(
|
||||
'xpack.monitoring.esNavigation.ingestPipelineModal.cancelButtonText',
|
||||
{ defaultMessage: 'Cancel' }
|
||||
)}
|
||||
confirmButtonDisabled={installing}
|
||||
onCancel={closeModal}
|
||||
onConfirm={async () => {
|
||||
setInstalling(true);
|
||||
try {
|
||||
await installPackage();
|
||||
closeModal();
|
||||
navigateToDashboard();
|
||||
} catch (e) {
|
||||
setError(e.body?.error || e.message);
|
||||
setInstalling(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{error && (
|
||||
<>
|
||||
<EuiCallOut
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.esNavigation.ingestPipelineModal.errorCalloutText"
|
||||
defaultMessage="Could not install the package due to an error: {error}"
|
||||
values={{ error }}
|
||||
/>
|
||||
}
|
||||
color="danger"
|
||||
iconType="alert"
|
||||
/>
|
||||
<EuiSpacer />
|
||||
</>
|
||||
)}
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.esNavigation.ingestPipelineModal.installPromptDescriptionText"
|
||||
defaultMessage="Viewing Ingest pipeline metrics requires installing the Elasticsearch integration. Do you
|
||||
want to install it now?"
|
||||
/>
|
||||
</p>
|
||||
</EuiConfirmModal>
|
||||
);
|
||||
};
|
|
@ -38,7 +38,9 @@ export interface TabMenuItem {
|
|||
id: string;
|
||||
label: string;
|
||||
testSubj?: string;
|
||||
route: string;
|
||||
route?: string;
|
||||
onClick?: () => void;
|
||||
prepend?: React.ReactNode;
|
||||
}
|
||||
export interface PageTemplateProps {
|
||||
title: string;
|
||||
|
@ -139,8 +141,10 @@ export const PageTemplate: React.FC<PageTemplateProps> = ({
|
|||
disabled={isDisabledTab(product)}
|
||||
title={item.label}
|
||||
data-test-subj={item.testSubj}
|
||||
href={createHref(item.route)}
|
||||
isSelected={isTabSelected(item.route)}
|
||||
href={item.route ? createHref(item.route) : undefined}
|
||||
isSelected={item.route ? isTabSelected(item.route) : undefined}
|
||||
onClick={item.onClick}
|
||||
prepend={item.prepend}
|
||||
>
|
||||
{item.label}
|
||||
</EuiTab>
|
||||
|
|
|
@ -13,6 +13,8 @@ import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
|||
export type { MonitoringConfig } from '../server';
|
||||
export type { MLJobs } from '../server/lib/elasticsearch/get_ml_jobs';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { DashboardStart } from '@kbn/dashboard-plugin/public';
|
||||
import { FleetStart } from '@kbn/fleet-plugin/public';
|
||||
|
||||
export interface MonitoringStartPluginDependencies {
|
||||
navigation: NavigationStart;
|
||||
|
@ -20,6 +22,8 @@ export interface MonitoringStartPluginDependencies {
|
|||
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
|
||||
usageCollection: UsageCollectionSetup;
|
||||
dataViews: DataViewsPublicPluginStart;
|
||||
dashboard?: DashboardStart;
|
||||
fleet?: FleetStart;
|
||||
}
|
||||
|
||||
interface LegacyStartDependencies {
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
"@kbn/core-elasticsearch-client-server-mocks",
|
||||
"@kbn/logging-mocks",
|
||||
"@kbn/io-ts-utils",
|
||||
"@kbn/dashboard-plugin",
|
||||
"@kbn/fleet-plugin",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue