-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[AWS Onboarding] Add 'take me to my data' functionality #290579
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
Merged
Supplementing
merged 16 commits into
elastic:main
from
Supplementing:aws-overview-dashboard-navigation
Sep 15, 2026
Merged
Changes from 11 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
2534188
feat(ingest-hub): navigate to [Metrics AWS] Overview dashboard from S…
Supplementing 1a75c6b
Merge branch 'main' into aws-overview-dashboard-navigation
Supplementing e395e9f
Changes from node scripts/check
kibanamachine 09686e8
fix(ingest-hub): replace useInstalledContent with dedicated useAwsOve…
Supplementing 22106dd
Merge branch 'main' into aws-overview-dashboard-navigation
Supplementing 4d6fa31
Changes from node scripts/check
kibanamachine 9dad9d5
refactor(ingest-hub): match AWS overview dashboard by ID not title
Supplementing eb43ca8
fix(ingest-hub): handle non-primary spaces in useAwsOverviewDashboardUrl
Supplementing 562d5b1
Merge branch 'main' into aws-overview-dashboard-navigation
Supplementing 7735c6b
Changes from node scripts/check
kibanamachine 23f5436
fix(ingest-hub): cast test refs as KibanaAssetReference to satisfy ts…
Supplementing 0a6e0df
Changes from node scripts/check
kibanamachine 59225bc
Update x-pack/platform/plugins/shared/ingest_hub/public/onboarding/st…
Supplementing 720bbb3
test(ingest-hub): assert no href on first render when spaces resolves…
Supplementing 5a7bfe1
nit(ingest-hub): use full GitHub link for AWS overview dashboard source
Supplementing 56dcad1
Merge branch 'main' into aws-overview-dashboard-navigation
Supplementing File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
.../onboarding/step_components/detect_and_review_step/use_aws_overview_dashboard_url.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| /* | ||
| * 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 { act, renderHook } from '@testing-library/react'; | ||
| import type { KibanaAssetReference } from '@kbn/fleet-plugin/common'; | ||
|
|
||
| jest.mock('@kbn/kibana-react-plugin/public', () => ({ | ||
| useKibana: jest.fn(), | ||
| })); | ||
|
|
||
| import { useKibana } from '@kbn/kibana-react-plugin/public'; | ||
| import { | ||
| useAwsOverviewDashboardUrl, | ||
| type InstallationSnapshot, | ||
| } from './use_aws_overview_dashboard_url'; | ||
|
|
||
| const mockUseKibana = useKibana as jest.Mock; | ||
| const mockPrepend = jest.fn((path: string) => `/base${path}`); | ||
| const mockGetActiveSpace = jest.fn(); | ||
|
|
||
| function setupKibana(spaceId?: string) { | ||
| mockGetActiveSpace.mockResolvedValue(spaceId ? { id: spaceId } : undefined); | ||
| mockUseKibana.mockReturnValue({ | ||
| services: { | ||
| http: { basePath: { prepend: mockPrepend } }, | ||
| spaces: spaceId !== undefined ? { getActiveSpace: mockGetActiveSpace } : undefined, | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| beforeEach(() => { | ||
| jest.clearAllMocks(); | ||
| setupKibana('default'); | ||
| }); | ||
|
|
||
| // The canonical package ID for [Metrics AWS] Overview, as shipped in elastic/integrations. | ||
| const OVERVIEW_ID = 'aws-fac28650-7349-11e9-816b-07687310a99a'; | ||
|
|
||
| // Cast as KibanaAssetReference — avoids assigning the string literal 'dashboard' to the | ||
| // KibanaSavedObjectType enum under CI's tsconfig.type_check.json compiled resolution. | ||
| const primaryRef = { id: OVERVIEW_ID, type: 'dashboard' } as KibanaAssetReference; | ||
| const otherRef = { id: 'aws-ec2-id', type: 'dashboard' } as KibanaAssetReference; | ||
|
|
||
| describe('useAwsOverviewDashboardUrl', () => { | ||
| it('returns undefined when installationInfo is undefined', async () => { | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(undefined)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBeUndefined(); | ||
| }); | ||
|
|
||
| describe('primary space (installed_kibana_space_id === currentSpaceId)', () => { | ||
| it('returns the basePath-prefixed URL when the overview ref is in installed_kibana', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [otherRef, primaryRef], | ||
| installed_kibana_space_id: 'default', | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBe(`/base/app/dashboards#/view/${OVERVIEW_ID}`); | ||
| }); | ||
|
|
||
| it('returns undefined when the overview dashboard is not in installed_kibana', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [otherRef], | ||
| installed_kibana_space_id: 'default', | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('treats missing installed_kibana_space_id as primary space', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [primaryRef], | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBe(`/base/app/dashboards#/view/${OVERVIEW_ID}`); | ||
| }); | ||
| }); | ||
|
|
||
| describe('non-primary space (installed_kibana_space_id !== currentSpaceId)', () => { | ||
| const SPACE_LOCAL_ID = 'some-space-specific-uuid'; | ||
|
|
||
| beforeEach(() => setupKibana('my-space')); | ||
|
|
||
| it('returns the URL using the space-local id matched by originId', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [primaryRef], // primary space refs (different space) | ||
| installed_kibana_space_id: 'default', | ||
| additional_spaces_installed_kibana: { | ||
| 'my-space': [ | ||
| { id: SPACE_LOCAL_ID, originId: OVERVIEW_ID, type: 'dashboard' } as KibanaAssetReference, | ||
| ], | ||
| }, | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBe(`/base/app/dashboards#/view/${SPACE_LOCAL_ID}`); | ||
| }); | ||
|
|
||
| it('returns undefined when the current space has no additional_spaces entry', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [primaryRef], | ||
| installed_kibana_space_id: 'default', | ||
| additional_spaces_installed_kibana: {}, | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('returns undefined when the space entry exists but has no overview dashboard', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [primaryRef], | ||
| installed_kibana_space_id: 'default', | ||
| additional_spaces_installed_kibana: { | ||
| 'my-space': [{ id: 'some-other-uuid', originId: 'aws-ec2-id', type: 'dashboard' } as KibanaAssetReference], | ||
| }, | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBeUndefined(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('spaces service unavailable', () => { | ||
| beforeEach(() => setupKibana(undefined)); | ||
|
|
||
| it('falls back to primary space logic when spaces service is absent', async () => { | ||
| const info: InstallationSnapshot = { | ||
| installed_kibana: [primaryRef], | ||
| installed_kibana_space_id: 'default', | ||
| }; | ||
| const { result } = renderHook(() => useAwsOverviewDashboardUrl(info)); | ||
| await act(async () => {}); | ||
| expect(result.current).toBe(`/base/app/dashboards#/view/${OVERVIEW_ID}`); | ||
| }); | ||
| }); | ||
| }); |
87 changes: 87 additions & 0 deletions
87
...ublic/onboarding/step_components/detect_and_review_step/use_aws_overview_dashboard_url.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /* | ||
| * 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 { useEffect, useState } from 'react'; | ||
| import type { CoreStart } from '@kbn/core/public'; | ||
| import { useKibana } from '@kbn/kibana-react-plugin/public'; | ||
| import type { KibanaAssetReference } from '@kbn/fleet-plugin/common'; | ||
| import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; | ||
|
|
||
| /** | ||
| * Canonical saved-object ID of the `[Metrics AWS] Overview` dashboard shipped with | ||
| * the `aws` integration package (elastic/integrations). Stable across renames. | ||
| * | ||
| * Source: packages/aws/kibana/dashboard/aws-fac28650-7349-11e9-816b-07687310a99a.json | ||
| */ | ||
| const AWS_METRICS_OVERVIEW_DASHBOARD_ID = 'aws-fac28650-7349-11e9-816b-07687310a99a'; | ||
|
|
||
| /** | ||
| * Minimal slice of Fleet's InstallationInfo needed for space-aware dashboard resolution. | ||
| * InstallationInfo is not exported from @kbn/fleet-plugin/common so we define the subset. | ||
| */ | ||
| export interface InstallationSnapshot { | ||
| installed_kibana: KibanaAssetReference[]; | ||
| /** The space where the package's Kibana assets were originally installed. */ | ||
| installed_kibana_space_id?: string; | ||
| /** Space-local asset refs for any spaces beyond the primary installation space. */ | ||
| additional_spaces_installed_kibana?: Record<string, KibanaAssetReference[]>; | ||
| } | ||
|
|
||
| /** | ||
| * Resolves the basePath-prefixed href to the `[Metrics AWS] Overview` dashboard, | ||
| * matched by dashboard ID (not title) following Fleet's `getDashboardIdForSpace` pattern | ||
| * (x-pack/platform/plugins/shared/fleet/public/.../dashboard_helpers.ts): | ||
| * | ||
| * - Primary space (`installed_kibana_space_id === currentSpaceId`): the canonical package | ||
| * ID is the saved-object ID directly — look in `installed_kibana`. | ||
| * - Any other space: Fleet re-keys saved objects; look in `additional_spaces_installed_kibana` | ||
| * for a ref where `originId === canonicalId` and use that ref's space-local `id`. | ||
| * | ||
| * Returns `undefined` while the current space is still resolving, or if the dashboard is | ||
| * not installed in the current space. | ||
| */ | ||
| export function useAwsOverviewDashboardUrl( | ||
| installationInfo: InstallationSnapshot | undefined | ||
| ): string | undefined { | ||
| const { services } = useKibana<CoreStart & { spaces?: SpacesPluginStart }>(); | ||
|
|
||
| // Resolve the current space ID. Defaults to 'default' so the primary-space path works | ||
| // immediately on first render in the common case. A non-default space triggers a | ||
| // re-render once getActiveSpace() resolves. | ||
| const [currentSpaceId, setCurrentSpaceId] = useState<string>('default'); | ||
| useEffect(() => { | ||
| if (!services.spaces) return; | ||
| services.spaces.getActiveSpace().then((space) => setCurrentSpaceId(space.id)); | ||
| }, [services.spaces]); | ||
|
|
||
| if (!installationInfo) return undefined; | ||
|
Supplementing marked this conversation as resolved.
Outdated
|
||
|
|
||
| const { installed_kibana, installed_kibana_space_id, additional_spaces_installed_kibana } = | ||
| installationInfo; | ||
|
|
||
| let dashboardId: string | undefined; | ||
|
|
||
| if (!installed_kibana_space_id || installed_kibana_space_id === currentSpaceId) { | ||
| // Primary space: the canonical package ID is the saved-object id directly. | ||
| // KibanaSavedObjectType.dashboard === 'dashboard' — literal avoids runtime enum import. | ||
| const ref = installed_kibana.find( | ||
| (k) => k.type === 'dashboard' && k.id === AWS_METRICS_OVERVIEW_DASHBOARD_ID | ||
| ); | ||
| dashboardId = ref?.id; | ||
| } else { | ||
| // Non-primary space: Fleet re-keys the saved object; match by originId. | ||
| const spaceRefs = additional_spaces_installed_kibana?.[currentSpaceId]; | ||
| const ref = spaceRefs?.find( | ||
| (k) => k.type === 'dashboard' && k.originId === AWS_METRICS_OVERVIEW_DASHBOARD_ID | ||
| ); | ||
| dashboardId = ref?.id; | ||
| } | ||
|
|
||
| return dashboardId | ||
| ? services.http.basePath.prepend(`/app/dashboards#/view/${dashboardId}`) | ||
| : undefined; | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.