mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
# Backport This will backport the following commits from `main` to `8.17`: - [[Fleet] Fix agent dashboard link accross multiple space (#201280)](https://github.com/elastic/kibana/pull/201280) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Nicolas Chaulet","email":"nicolas.chaulet@elastic.co"},"sourceCommit":{"committedDate":"2024-11-22T18:00:22Z","message":"[Fleet] Fix agent dashboard link accross multiple space (#201280)","sha":"8e6698f6e70681d9bdb23ff88a2a76cdde3a38c0","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","v9.0.0","backport:prev-major"],"title":"[Fleet] Fix agent dashboard link accross multiple space","number":201280,"url":"https://github.com/elastic/kibana/pull/201280","mergeCommit":{"message":"[Fleet] Fix agent dashboard link accross multiple space (#201280)","sha":"8e6698f6e70681d9bdb23ff88a2a76cdde3a38c0"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/201280","number":201280,"mergeCommit":{"message":"[Fleet] Fix agent dashboard link accross multiple space (#201280)","sha":"8e6698f6e70681d9bdb23ff88a2a76cdde3a38c0"}}]}] BACKPORT--> Co-authored-by: Nicolas Chaulet <nicolas.chaulet@elastic.co>
This commit is contained in:
parent
142f3fa178
commit
4e05cb7979
5 changed files with 147 additions and 24 deletions
|
@ -21,6 +21,7 @@ jest.mock('../../../../../../hooks/use_fleet_status', () => ({
|
|||
FleetStatusProvider: (props: any) => {
|
||||
return props.children;
|
||||
},
|
||||
useFleetStatus: jest.fn().mockReturnValue({ spaceId: 'default' }),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../../hooks/use_request/epm');
|
||||
|
@ -30,7 +31,7 @@ jest.mock('../../../../../../hooks/use_locator', () => {
|
|||
useDashboardLocator: jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
id: 'DASHBOARD_APP_LOCATOR',
|
||||
getRedirectUrl: jest.fn().mockResolvedValue('app/dashboards#/view/elastic_agent-a0001'),
|
||||
getRedirectUrl: jest.fn().mockReturnValue('app/dashboards#/view/elastic_agent-a0001'),
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
@ -43,6 +44,10 @@ describe('AgentDashboardLink', () => {
|
|||
data: {
|
||||
item: {
|
||||
status: 'installed',
|
||||
installationInfo: {
|
||||
install_status: 'installed',
|
||||
installed_kibana_space_id: 'default',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ReturnType<typeof useGetPackageInfoByKeyQuery>);
|
||||
|
|
|
@ -10,21 +10,49 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { EuiButton, EuiToolTip } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useGetPackageInfoByKeyQuery, useLink, useDashboardLocator } from '../../../../hooks';
|
||||
import type { GetInfoResponse } from '../../../../../../../common/types';
|
||||
import {
|
||||
useGetPackageInfoByKeyQuery,
|
||||
useLink,
|
||||
useDashboardLocator,
|
||||
useFleetStatus,
|
||||
} from '../../../../hooks';
|
||||
import type { Agent, AgentPolicy } from '../../../../types';
|
||||
import {
|
||||
FLEET_ELASTIC_AGENT_PACKAGE,
|
||||
DASHBOARD_LOCATORS_IDS,
|
||||
} from '../../../../../../../common/constants';
|
||||
import { getDashboardIdForSpace } from '../../services/dashboard_helpers';
|
||||
|
||||
function isKibanaAssetsInstalledInSpace(spaceId: string | undefined, res?: GetInfoResponse) {
|
||||
if (res?.item?.status !== 'installed') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const installationInfo = res.item.installationInfo;
|
||||
|
||||
if (!installationInfo || installationInfo.install_status !== 'installed') {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
installationInfo.installed_kibana_space_id === spaceId ||
|
||||
(spaceId && installationInfo.additional_spaces_installed_kibana?.[spaceId])
|
||||
);
|
||||
}
|
||||
|
||||
function useAgentDashboardLink(agent: Agent) {
|
||||
const { isLoading, data } = useGetPackageInfoByKeyQuery(FLEET_ELASTIC_AGENT_PACKAGE);
|
||||
const { spaceId } = useFleetStatus();
|
||||
|
||||
const isInstalled = data?.item.status === 'installed';
|
||||
const isInstalled = isKibanaAssetsInstalledInSpace(spaceId, data);
|
||||
const dashboardLocator = useDashboardLocator();
|
||||
|
||||
const link = dashboardLocator?.getRedirectUrl({
|
||||
dashboardId: DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_METRICS,
|
||||
dashboardId: getDashboardIdForSpace(
|
||||
spaceId,
|
||||
data,
|
||||
DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_METRICS
|
||||
),
|
||||
query: {
|
||||
language: 'kuery',
|
||||
query: `elastic_agent.id:${agent.id}`,
|
||||
|
|
|
@ -5,49 +5,69 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { DASHBOARD_LOCATORS_IDS } from '../../../../../../../common/constants';
|
||||
import {
|
||||
DASHBOARD_LOCATORS_IDS,
|
||||
FLEET_ELASTIC_AGENT_PACKAGE,
|
||||
} from '../../../../../../../common/constants';
|
||||
|
||||
import { useDashboardLocator, useStartServices } from '../../../../hooks';
|
||||
import {
|
||||
useDashboardLocator,
|
||||
useFleetStatus,
|
||||
useGetPackageInfoByKeyQuery,
|
||||
useStartServices,
|
||||
} from '../../../../hooks';
|
||||
|
||||
import { getDashboardIdForSpace } from '../../services/dashboard_helpers';
|
||||
|
||||
const useDashboardExists = (dashboardId: string) => {
|
||||
const [dashboardExists, setDashboardExists] = React.useState<boolean>(false);
|
||||
const [loading, setLoading] = React.useState<boolean>(true);
|
||||
const { dashboard: dashboardPlugin } = useStartServices();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDashboard = async () => {
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['dashboard_exists', dashboardId],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
const findDashboardsService = await dashboardPlugin.findDashboardsService();
|
||||
const [dashboard] = await findDashboardsService.findByIds([dashboardId]);
|
||||
setLoading(false);
|
||||
setDashboardExists(dashboard?.status === 'success');
|
||||
return dashboard?.status === 'success';
|
||||
} catch (e) {
|
||||
setLoading(false);
|
||||
setDashboardExists(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
fetchDashboard();
|
||||
}, [dashboardId, dashboardPlugin]);
|
||||
|
||||
return { dashboardExists, loading };
|
||||
},
|
||||
});
|
||||
return { dashboardExists: data ?? false, loading: isLoading };
|
||||
};
|
||||
|
||||
export const DashboardsButtons: React.FunctionComponent = () => {
|
||||
const { data } = useGetPackageInfoByKeyQuery(FLEET_ELASTIC_AGENT_PACKAGE);
|
||||
const { spaceId } = useFleetStatus();
|
||||
|
||||
const dashboardLocator = useDashboardLocator();
|
||||
|
||||
const getDashboardHref = (dashboardId: string) => {
|
||||
return dashboardLocator?.getRedirectUrl({ dashboardId }) || '';
|
||||
};
|
||||
|
||||
const { dashboardExists, loading: dashboardLoading } = useDashboardExists(
|
||||
const elasticAgentOverviewDashboardId = getDashboardIdForSpace(
|
||||
spaceId,
|
||||
data,
|
||||
DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_OVERVIEW
|
||||
);
|
||||
|
||||
const elasticAgentInfoDashboardId = getDashboardIdForSpace(
|
||||
spaceId,
|
||||
data,
|
||||
DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_INFO
|
||||
);
|
||||
|
||||
const { dashboardExists, loading: dashboardLoading } = useDashboardExists(
|
||||
elasticAgentOverviewDashboardId
|
||||
);
|
||||
|
||||
if (dashboardLoading || !dashboardExists) {
|
||||
return null;
|
||||
}
|
||||
|
@ -58,7 +78,7 @@ export const DashboardsButtons: React.FunctionComponent = () => {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
iconType="dashboardApp"
|
||||
href={getDashboardHref(DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_OVERVIEW)}
|
||||
href={getDashboardHref(elasticAgentOverviewDashboardId)}
|
||||
data-test-subj="ingestOverviewLinkButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
@ -70,7 +90,7 @@ export const DashboardsButtons: React.FunctionComponent = () => {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
iconType="dashboardApp"
|
||||
href={getDashboardHref(DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_INFO)}
|
||||
href={getDashboardHref(elasticAgentInfoDashboardId)}
|
||||
data-test-subj="agentInfoLinkButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 type { GetInfoResponse } from '../../../../../../common';
|
||||
|
||||
import { getDashboardIdForSpace } from './dashboard_helpers';
|
||||
|
||||
const PKG_INFO = {
|
||||
item: {
|
||||
status: 'installed',
|
||||
installationInfo: {
|
||||
install_status: 'installed',
|
||||
installed_kibana_space_id: 'default',
|
||||
additional_spaces_installed_kibana: {
|
||||
test: [
|
||||
{
|
||||
id: 'test-destination-1',
|
||||
originId: 'test-id-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as GetInfoResponse;
|
||||
|
||||
describe('getDashboardIdForSpace', () => {
|
||||
it('return the same id if package is installed in the same space', () => {
|
||||
expect(() => getDashboardIdForSpace('default', PKG_INFO, 'test-id-1'));
|
||||
});
|
||||
|
||||
it('return the destination ID if package is installed in an additionnal space', () => {
|
||||
expect(() => getDashboardIdForSpace('test', PKG_INFO, 'test-id-1'));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
|
||||
|
||||
import type { GetInfoResponse } from '../../../../../../common';
|
||||
|
||||
export function getDashboardIdForSpace(
|
||||
spaceId: string = DEFAULT_SPACE_ID,
|
||||
res: GetInfoResponse | undefined,
|
||||
dashboardId: string
|
||||
) {
|
||||
if (res?.item?.status !== 'installed') {
|
||||
return dashboardId;
|
||||
}
|
||||
|
||||
const installationInfo = res.item.installationInfo;
|
||||
|
||||
if (!installationInfo || installationInfo?.installed_kibana_space_id === spaceId) {
|
||||
return dashboardId;
|
||||
}
|
||||
|
||||
return (
|
||||
installationInfo.additional_spaces_installed_kibana?.[spaceId]?.find(
|
||||
({ originId }) => originId === dashboardId
|
||||
)?.id ?? dashboardId
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue