-
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] Add raw status to Agent details UI (#154826)
## Summary Make raw agent status discoverable in Fleet UI, under `Agent details` tab. Closes #154067 ### Screenshots <img width="1918" alt="Screenshot 2023-04-19 at 12 14 48" src="https://user-images.githubusercontent.com/23701614/233059955-7f066ad5-39cd-4685-b76b-41bc31ede4e8.png"> <img width="1918" alt="Screenshot 2023-04-19 at 13 04 06" src="https://user-images.githubusercontent.com/23701614/233059973-3f1b507f-d0bf-48ab-929b-c567f9814377.png"> ### UX checklist - [ ] Action link title (`View agent JSON`) - [ ] Flyout title (`{agentName} agent details`) - [ ] Download button - [ ] Download button label (`Download JSON`) - [ ] Downloaded file name (`{agentName}-agent-details.json`) ### Testing steps 1. Run Kibana in dev on this branch. 2. In Fleet, click on an agent to get to the agent details page. 3. There should be a new `View agent JSON` item in the `Actions` menu. Click it. 4. A new flyout should open with the agent details in JSON format. Clicking outside of the flyout or on the `Close` button should close the flyout. 5. The `Download JSON` button should download the JSON correctly. ### Checklist - [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) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [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 - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
- Loading branch information
1 parent
cd90b11
commit b97b18e
Showing
3 changed files
with
218 additions
and
1 deletion.
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
74 changes: 74 additions & 0 deletions
74
...ns/fleet/sections/agents/agent_details_page/components/agent_details_json_flyout.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,74 @@ | ||
/* | ||
* 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 { render } from '@testing-library/react'; | ||
|
||
import type { Agent } from '../../../../types'; | ||
import { useStartServices } from '../../../../hooks'; | ||
|
||
import { AgentDetailsJsonFlyout } from './agent_details_json_flyout'; | ||
|
||
jest.mock('../../../../hooks'); | ||
|
||
const mockUseStartServices = useStartServices as jest.Mock; | ||
|
||
describe('AgentDetailsJsonFlyout', () => { | ||
const agent: Agent = { | ||
id: '123', | ||
packages: [], | ||
type: 'PERMANENT', | ||
active: true, | ||
enrolled_at: `${Date.now()}`, | ||
user_provided_metadata: {}, | ||
local_metadata: {}, | ||
}; | ||
|
||
beforeEach(() => { | ||
mockUseStartServices.mockReturnValue({ | ||
docLinks: { links: { fleet: { troubleshooting: 'https://elastic.co' } } }, | ||
}); | ||
}); | ||
|
||
const renderComponent = () => { | ||
return render(<AgentDetailsJsonFlyout agent={agent} onClose={jest.fn()} />); | ||
}; | ||
|
||
it('renders a title with the agent id if host name is not defined', () => { | ||
const result = renderComponent(); | ||
expect(result.getByText("'123' agent details")).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders a title with the agent host name if defined', () => { | ||
agent.local_metadata = { | ||
host: { | ||
hostname: '456', | ||
}, | ||
}; | ||
const result = renderComponent(); | ||
expect(result.getByText("'456' agent details")).toBeInTheDocument(); | ||
}); | ||
|
||
it('does not add a link to the page after clicking Download', () => { | ||
const result = renderComponent(); | ||
const downloadButton = result.getByRole('button', { name: 'Download JSON' }); | ||
const anchorMocked = { | ||
href: '', | ||
click: jest.fn(), | ||
download: '', | ||
setAttribute: jest.fn(), | ||
} as any; | ||
const createElementSpyOn = jest | ||
.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(anchorMocked); | ||
|
||
downloadButton.click(); | ||
expect(createElementSpyOn).toBeCalledWith('a'); | ||
expect(result.queryAllByRole('link')).toHaveLength(1); // The only link is the one from the flyout's description. | ||
expect(result.getByRole('link')).toHaveAttribute('href', 'https://elastic.co'); | ||
}); | ||
}); |
106 changes: 106 additions & 0 deletions
106
...cations/fleet/sections/agents/agent_details_page/components/agent_details_json_flyout.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,106 @@ | ||
/* | ||
* 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, { memo } from 'react'; | ||
import { FormattedMessage } from '@kbn/i18n-react'; | ||
import { | ||
EuiButton, | ||
EuiButtonEmpty, | ||
EuiCodeBlock, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
EuiFlyout, | ||
EuiFlyoutBody, | ||
EuiFlyoutFooter, | ||
EuiFlyoutHeader, | ||
EuiLink, | ||
EuiSpacer, | ||
EuiText, | ||
EuiTitle, | ||
} from '@elastic/eui'; | ||
|
||
import type { Agent } from '../../../../types'; | ||
import { useStartServices } from '../../../../hooks'; | ||
|
||
export const AgentDetailsJsonFlyout = memo<{ agent: Agent; onClose: () => void }>( | ||
({ agent, onClose }) => { | ||
const agentToJson = JSON.stringify(agent, null, 2); | ||
const agentName = | ||
typeof agent.local_metadata?.host?.hostname === 'string' | ||
? agent.local_metadata.host.hostname | ||
: agent.id; | ||
|
||
const downloadJson = () => { | ||
const link = document.createElement('a'); | ||
link.href = `data:text/json;charset=utf-8,${encodeURIComponent(agentToJson)}`; | ||
link.download = `${agentName}-agent-details.json`; | ||
link.click(); | ||
}; | ||
|
||
const { docLinks } = useStartServices(); | ||
|
||
return ( | ||
<EuiFlyout onClose={onClose} size="l" maxWidth={640}> | ||
<EuiFlyoutHeader hasBorder> | ||
<EuiTitle size="m"> | ||
<h2> | ||
<FormattedMessage | ||
id="xpack.fleet.agentDetails.jsonFlyoutTitle" | ||
defaultMessage="'{name}' agent details" | ||
values={{ | ||
name: agentName, | ||
}} | ||
/> | ||
</h2> | ||
</EuiTitle> | ||
</EuiFlyoutHeader> | ||
<EuiFlyoutBody> | ||
<EuiText> | ||
<p> | ||
<FormattedMessage | ||
id="xpack.fleet.agentDetails.jsonFlyoutDescription" | ||
defaultMessage="The JSON below is the raw agent data tracked by Fleet. This data can be useful for debugging or troubleshooting Elastic Agent. For more information, see the {doc}." | ||
values={{ | ||
doc: ( | ||
<EuiLink href={docLinks.links.fleet.troubleshooting}> | ||
<FormattedMessage | ||
id="xpack.fleet.agentDetails.jsonFlyoutDocLink" | ||
defaultMessage="troubleshooting documentation" | ||
/> | ||
</EuiLink> | ||
), | ||
}} | ||
/> | ||
</p> | ||
</EuiText> | ||
<EuiSpacer /> | ||
<EuiCodeBlock language="json">{agentToJson}</EuiCodeBlock> | ||
</EuiFlyoutBody> | ||
<EuiFlyoutFooter> | ||
<EuiFlexGroup justifyContent="spaceBetween"> | ||
<EuiFlexItem grow={false}> | ||
<EuiButtonEmpty onClick={onClose} flush="left"> | ||
<FormattedMessage | ||
id="xpack.fleet.agentDetails.agentDetailsJsonFlyoutCloseButtonLabel" | ||
defaultMessage="Close" | ||
/> | ||
</EuiButtonEmpty> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={false}> | ||
<EuiButton iconType="download" onClick={downloadJson}> | ||
<FormattedMessage | ||
id="xpack.fleet.agentDetails.agentDetailsJsonDownloadButtonLabel" | ||
defaultMessage="Download JSON" | ||
/> | ||
</EuiButton> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiFlyoutFooter> | ||
</EuiFlyout> | ||
); | ||
} | ||
); |