-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fleet] Show remote es output error state on UI (#172181)
## Summary Relates elastic/fleet-server#3116 Relates #104986 Reading latest output health state from `logs-fleet_server.output_health-default` data stream by output id, and displaying error state on UI - Edit Output flyout. Steps to verify: - enable feature flag `remoteESOutput` - add `remote_elasticsearch` output, can be a non-existent host for this test - add the output as monitoring output of an agent policy - run fleet-server with the changes [here](elastic/fleet-server#3116) - enroll an agent - wait until fleet-server starts reporting degraded state in the output health data stream - open edit output flyout on UI and verify that the error state is visible - when the connection is back again (update host to a valid one, or remote es was temporarily down), the error state goes away <img width="568" alt="image" src="https://github.com/elastic/kibana/assets/90178898/46d0cf95-6aa4-4f7c-8608-4362ada4eb6c"> The UI was suggested in the design doc: https://docs.google.com/document/d/19D0bX7oURf0yms4qemfqDyisw_IYB-OVw4oU-t4lf18/edit#bookmark=id.595r8l91kaq8 ### Notes/suggestions: - We might want to add the output state to the output list as well (maybe as badges like agent health?) as it's not too visible in the flyout (have to scroll down). - Also the error state will be reported earliest when an agent is enrolled and fleet-server can't create api key, so not immediately when the output is added. It would be good to show the time of the last state (e.g. how we display on agents last checkin x minutes ago) - I think it would be beneficial to display the healthy state too. Added badges to output list: <img width="1233" alt="image" src="https://github.com/elastic/kibana/assets/90178898/07ff06ec-b778-4420-975b-b46a0a18c7cc"> Added healthy state UI to Edit output: <img width="627" alt="image" src="https://github.com/elastic/kibana/assets/90178898/4222d849-c957-41d7-9606-b58493264115"> ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
- Loading branch information
1 parent
159f361
commit ae5e2fd
Showing
23 changed files
with
609 additions
and
21 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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
31 changes: 31 additions & 0 deletions
31
x-pack/plugins/fleet/common/openapi/paths/output_health@{output_id}.yaml
This file contains 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,31 @@ | ||
get: | ||
summary: Get latest output health | ||
tags: | ||
- Outputs | ||
responses: | ||
'200': | ||
description: OK | ||
content: | ||
application/json: | ||
schema: | ||
type: object | ||
properties: | ||
state: | ||
type: string | ||
description: state of output, HEALTHY or DEGRADED | ||
message: | ||
type: string | ||
description: long message if unhealthy | ||
timestamp: | ||
type: string | ||
description: timestamp of reported state | ||
'400': | ||
$ref: ../components/responses/error.yaml | ||
operationId: get-output-health | ||
parameters: | ||
- schema: | ||
type: string | ||
name: outputId | ||
in: path | ||
required: true | ||
|
This file contains 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 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 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
143 changes: 143 additions & 0 deletions
143
...applications/fleet/sections/settings/components/edit_output_flyout/output_health.test.tsx
This file contains 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,143 @@ | ||
/* | ||
* 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 from 'react'; | ||
import { waitFor } from '@testing-library/react'; | ||
|
||
import type { Output } from '../../../../types'; | ||
import { createFleetTestRendererMock } from '../../../../../../mock'; | ||
|
||
import { sendGetOutputHealth, useStartServices } from '../../../../hooks'; | ||
|
||
import { OutputHealth } from './output_health'; | ||
|
||
jest.mock('../../../../hooks', () => { | ||
return { | ||
...jest.requireActual('../../../../hooks'), | ||
useStartServices: jest.fn(), | ||
sendGetOutputHealth: jest.fn(), | ||
}; | ||
}); | ||
|
||
jest.mock('@elastic/eui', () => { | ||
return { | ||
...jest.requireActual('@elastic/eui'), | ||
EuiToolTip: (props: any) => ( | ||
<div data-test-subj="outputHealthBadgeTooltip" data-tooltip-content={props.content}> | ||
{props.children} | ||
</div> | ||
), | ||
}; | ||
}); | ||
|
||
const mockUseStartServices = useStartServices as jest.Mock; | ||
|
||
const mockSendGetOutputHealth = sendGetOutputHealth as jest.Mock; | ||
|
||
describe('OutputHealth', () => { | ||
function render(output: Output, showBadge?: boolean) { | ||
const renderer = createFleetTestRendererMock(); | ||
|
||
const utils = renderer.render(<OutputHealth output={output} showBadge={showBadge} />); | ||
|
||
return { utils }; | ||
} | ||
|
||
const mockStartServices = () => { | ||
mockUseStartServices.mockReturnValue({ | ||
notifications: { toasts: {} }, | ||
}); | ||
}; | ||
|
||
beforeEach(() => { | ||
mockStartServices(); | ||
}); | ||
|
||
it('should render output health component when degraded', async () => { | ||
mockSendGetOutputHealth.mockResolvedValue({ | ||
data: { state: 'DEGRADED', message: 'connection error', timestamp: '2023-11-30T14:25:31Z' }, | ||
}); | ||
const { utils } = render({ | ||
type: 'remote_elasticsearch', | ||
id: 'remote', | ||
name: 'Remote ES', | ||
hosts: ['https://remote-es:443'], | ||
} as Output); | ||
|
||
expect(mockSendGetOutputHealth).toHaveBeenCalled(); | ||
|
||
await waitFor(async () => { | ||
expect(utils.getByTestId('outputHealthDegradedCallout').textContent).toContain( | ||
'Unable to connect to "Remote ES" at https://remote-es:443. Please check the details are correct.' | ||
); | ||
}); | ||
}); | ||
|
||
it('should render output health component when healthy', async () => { | ||
mockSendGetOutputHealth.mockResolvedValue({ | ||
data: { state: 'HEALTHY', message: '', timestamp: '2023-11-30T14:25:31Z' }, | ||
}); | ||
const { utils } = render({ | ||
type: 'remote_elasticsearch', | ||
id: 'remote', | ||
name: 'Remote ES', | ||
hosts: ['https://remote-es:443'], | ||
} as Output); | ||
|
||
expect(mockSendGetOutputHealth).toHaveBeenCalled(); | ||
|
||
await waitFor(async () => { | ||
expect(utils.getByTestId('outputHealthHealthyCallout').textContent).toContain( | ||
'Connection with remote output established.' | ||
); | ||
}); | ||
}); | ||
|
||
it('should render output health badge when degraded', async () => { | ||
mockSendGetOutputHealth.mockResolvedValue({ | ||
data: { state: 'DEGRADED', message: 'connection error', timestamp: '2023-11-30T14:25:31Z' }, | ||
}); | ||
const { utils } = render( | ||
{ | ||
type: 'remote_elasticsearch', | ||
id: 'remote', | ||
name: 'Remote ES', | ||
hosts: ['https://remote-es:443'], | ||
} as Output, | ||
true | ||
); | ||
|
||
expect(mockSendGetOutputHealth).toHaveBeenCalled(); | ||
|
||
await waitFor(async () => { | ||
expect(utils.getByTestId('outputHealthDegradedBadge')).not.toBeNull(); | ||
expect(utils.getByTestId('outputHealthBadgeTooltip')).not.toBeNull(); | ||
}); | ||
}); | ||
|
||
it('should render output health badge when healthy', async () => { | ||
mockSendGetOutputHealth.mockResolvedValue({ | ||
data: { state: 'HEALTHY', message: '', timestamp: '2023-11-30T14:25:31Z' }, | ||
}); | ||
const { utils } = render( | ||
{ | ||
type: 'remote_elasticsearch', | ||
id: 'remote', | ||
name: 'Remote ES', | ||
hosts: ['https://remote-es:443'], | ||
} as Output, | ||
true | ||
); | ||
|
||
expect(mockSendGetOutputHealth).toHaveBeenCalled(); | ||
|
||
await waitFor(async () => { | ||
expect(utils.getByTestId('outputHealthHealthyBadge')).not.toBeNull(); | ||
expect(utils.getByTestId('outputHealthBadgeTooltip')).not.toBeNull(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.