-
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.
* Fix agent table empty prompt * First pass at agent enrollment flyout with placeholders * Move enrollment commands into separate file and enable templated vars * Use default double braces for templating
- Loading branch information
Showing
7 changed files
with
424 additions
and
6 deletions.
There are no files selected for viewing
139 changes: 139 additions & 0 deletions
139
x-pack/legacy/plugins/fleet/public/pages/agent_list/components/agent_enrollment.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,139 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
import React, { useState, Fragment } from 'react'; | ||
import { FormattedMessage } from '@kbn/i18n/react'; | ||
import { | ||
EuiFlyout, | ||
EuiFlyoutHeader, | ||
EuiTitle, | ||
EuiFlyoutBody, | ||
EuiFlyoutFooter, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
EuiButtonEmpty, | ||
EuiButton, | ||
EuiSpacer, | ||
EuiText, | ||
EuiFilterGroup, | ||
EuiFilterButton, | ||
} from '@elastic/eui'; | ||
import { FrontendLibs } from '../../../lib/types'; | ||
import { | ||
ShellEnrollmentInstructions, | ||
ContainerEnrollmentInstructions, | ||
ToolsEnrollmentInstructions, | ||
} from './enrollment_instructions'; | ||
|
||
interface RouterProps { | ||
libs: FrontendLibs; | ||
onClose: () => void; | ||
} | ||
|
||
export const AgentEnrollmentFlyout: React.SFC<RouterProps> = ({ libs, onClose }) => { | ||
const [quickInstallType, setQuickInstallType] = useState<'shell' | 'container' | 'tools'>( | ||
'shell' | ||
); | ||
|
||
const renderHeader = () => ( | ||
<EuiFlyoutHeader hasBorder aria-labelledby="FleetAgentEnrollmentFlyoutTitle"> | ||
<EuiTitle size="m"> | ||
<h2 id="FleetAgentEnrollmentFlyoutTitle"> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.flyoutTitle" | ||
defaultMessage="Install agent" | ||
/> | ||
</h2> | ||
</EuiTitle> | ||
<EuiSpacer size="s" /> | ||
<EuiText color="subdued"> | ||
<p> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.flyoutDescription" | ||
defaultMessage="Enroll a new agent into Fleet." | ||
/> | ||
</p> | ||
</EuiText> | ||
</EuiFlyoutHeader> | ||
); | ||
|
||
const renderInstructions = () => ( | ||
<Fragment> | ||
<EuiText> | ||
<h5> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.quickInstallTitle" | ||
defaultMessage="Quick installation" | ||
/> | ||
</h5> | ||
</EuiText> | ||
<EuiSpacer size="s" /> | ||
<EuiFilterGroup> | ||
<EuiFilterButton | ||
hasActiveFilters={quickInstallType === 'shell'} | ||
onClick={() => setQuickInstallType('shell')} | ||
> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.shellInstallButtonText" | ||
defaultMessage="Shell" | ||
/> | ||
</EuiFilterButton> | ||
<EuiFilterButton | ||
hasActiveFilters={quickInstallType === 'container'} | ||
onClick={() => setQuickInstallType('container')} | ||
> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.containerInstallButtonText" | ||
defaultMessage="Container" | ||
/> | ||
</EuiFilterButton> | ||
<EuiFilterButton | ||
hasActiveFilters={quickInstallType === 'tools'} | ||
onClick={() => setQuickInstallType('tools')} | ||
> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.toolsInstallButtonText" | ||
defaultMessage="Tools" | ||
/> | ||
</EuiFilterButton> | ||
</EuiFilterGroup> | ||
<EuiSpacer size="m" /> | ||
{quickInstallType === 'shell' ? ( | ||
<ShellEnrollmentInstructions | ||
kibanaUrl={`${window.location.origin}${libs.framework.info.basePath}`} | ||
/> | ||
) : null} | ||
{quickInstallType === 'container' ? <ContainerEnrollmentInstructions /> : null} | ||
{quickInstallType === 'tools' ? <ToolsEnrollmentInstructions /> : null} | ||
</Fragment> | ||
); | ||
|
||
const renderBody = () => <EuiFlyoutBody>{renderInstructions()}</EuiFlyoutBody>; | ||
|
||
const renderFooter = () => ( | ||
<EuiFlyoutFooter> | ||
<EuiFlexGroup justifyContent="spaceBetween"> | ||
<EuiFlexItem grow={false}> | ||
<EuiButtonEmpty iconType="cross" onClick={onClose} flush="left"> | ||
Close | ||
</EuiButtonEmpty> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={false}> | ||
<EuiButton fill onClick={onClose}> | ||
Continue | ||
</EuiButton> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiFlyoutFooter> | ||
); | ||
|
||
return ( | ||
<EuiFlyout onClose={onClose} size="m" maxWidth={650}> | ||
{renderHeader()} | ||
{renderBody()} | ||
{renderFooter()} | ||
</EuiFlyout> | ||
); | ||
}; |
10 changes: 10 additions & 0 deletions
10
...gins/fleet/public/pages/agent_list/components/enrollment_instructions/container/index.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,10 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
import React from 'react'; | ||
|
||
export const ContainerEnrollmentInstructions: React.SFC = () => { | ||
return <div>Container instructions</div>; | ||
}; |
64 changes: 64 additions & 0 deletions
64
...legacy/plugins/fleet/public/pages/agent_list/components/enrollment_instructions/index.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,64 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
import React from 'react'; | ||
import { EuiSteps, EuiText, EuiCodeBlock } from '@elastic/eui'; | ||
import { Writer } from 'mustache'; | ||
|
||
export { ShellEnrollmentInstructions } from './shell'; | ||
export { ContainerEnrollmentInstructions } from './container'; | ||
export { ToolsEnrollmentInstructions } from './tools'; | ||
|
||
export type ManualEnrollmentInstructions = Array<{ | ||
title: string; | ||
textPre?: string; | ||
commands?: string; | ||
commandsLang?: 'bash' | 'yaml'; | ||
}>; | ||
|
||
export const ManualEnrollmentSteps: React.SFC<{ instructions: ManualEnrollmentInstructions }> = ({ | ||
instructions, | ||
}) => ( | ||
<EuiSteps | ||
steps={instructions.map(({ title, textPre, commands, commandsLang }) => ({ | ||
title, | ||
children: ( | ||
<EuiText size="s"> | ||
{textPre ? <p>{textPre}</p> : null} | ||
{commands ? ( | ||
// TODO: Increase overflowHeight when https://github.com/elastic/eui/issues/2435 is fixed | ||
// or be smarter with setting this number before release | ||
<EuiCodeBlock overflowHeight={150} language={commandsLang || 'bash'} isCopyable> | ||
{replaceTemplateStrings(commands.trim())} | ||
</EuiCodeBlock> | ||
) : null} | ||
</EuiText> | ||
), | ||
}))} | ||
/> | ||
); | ||
|
||
// Setup for replacing template variables in install instructions | ||
const mustacheWriter = new Writer(); | ||
|
||
// do not html escape output | ||
// @ts-ignore | ||
mustacheWriter.escapedValue = function escapedValue(token, context) { | ||
const value = context.lookup(token[1]); | ||
if (value != null) { | ||
return value; | ||
} | ||
}; | ||
|
||
// Configure available variable values | ||
export function replaceTemplateStrings(text: string = '') { | ||
const variables = { | ||
config: { | ||
enrollmentToken: 'sometesttoken', | ||
}, | ||
}; | ||
mustacheWriter.parse(text); | ||
return mustacheWriter.render(text, variables, () => {}); | ||
} |
145 changes: 145 additions & 0 deletions
145
.../plugins/fleet/public/pages/agent_list/components/enrollment_instructions/shell/index.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,145 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
import React, { useState, Fragment } from 'react'; | ||
import { | ||
EuiFieldText, | ||
EuiCopy, | ||
EuiButtonEmpty, | ||
EuiPopover, | ||
EuiSpacer, | ||
EuiContextMenuPanel, | ||
EuiContextMenuItem, | ||
} from '@elastic/eui'; | ||
import { FormattedMessage } from '@kbn/i18n/react'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { ManualEnrollmentInstructions, ManualEnrollmentSteps } from '../'; | ||
import * as MAC_COMMANDS from './mac_commands'; | ||
|
||
// No need for i18n as these are platform names | ||
const PLATFORMS = { | ||
macos: 'macOS', | ||
windows: 'Windows', | ||
linux: 'Linux', | ||
}; | ||
|
||
// Manual instructions based on platform | ||
const PLATFORM_INSTRUCTIONS: { | ||
[key: string]: ManualEnrollmentInstructions; | ||
} = { | ||
macos: [ | ||
{ | ||
title: i18n.translate('xpack.fleet.agentEnrollment.typeShell.manualInstall.stepOneTitle', { | ||
defaultMessage: 'Download and install Elastic Agent', | ||
}), | ||
textPre: 'Lorem ipsum instructions here.', | ||
commands: MAC_COMMANDS.INSTALL, | ||
}, | ||
{ | ||
title: i18n.translate('xpack.fleet.agentEnrollment.typeShell.manualInstall.stepTwoTitle', { | ||
defaultMessage: 'Edit the configuration', | ||
}), | ||
textPre: 'Modify the configuration file to set the connection information:', | ||
commands: MAC_COMMANDS.CONFIG, | ||
commandsLang: 'yaml', | ||
}, | ||
{ | ||
title: i18n.translate('xpack.fleet.agentEnrollment.typeShell.manualInstall.stepThreeTitle', { | ||
defaultMessage: 'Start the agent', | ||
}), | ||
commands: MAC_COMMANDS.START, | ||
}, | ||
], | ||
}; | ||
|
||
interface Props { | ||
kibanaUrl: string; | ||
} | ||
|
||
export const ShellEnrollmentInstructions: React.SFC<Props> = ({ kibanaUrl }) => { | ||
// Platform state | ||
const [currentPlatform, setCurrentPlatform] = useState<keyof typeof PLATFORMS>('macos'); | ||
const [isPlatformOptionsOpen, setIsPlatformOptionsOpen] = useState<boolean>(false); | ||
const [isManualInstallationOpen, setIsManualInstallationOpen] = useState<boolean>(false); | ||
|
||
// Build quick installation command | ||
const quickInstallInstructions = `curl ${kibanaUrl}/api/fleet/install/${currentPlatform} | bash`; | ||
|
||
return ( | ||
<Fragment> | ||
<EuiFieldText | ||
readOnly | ||
value={quickInstallInstructions} | ||
fullWidth | ||
prepend={ | ||
<EuiPopover | ||
button={ | ||
<EuiButtonEmpty | ||
size="xs" | ||
iconType="arrowDown" | ||
iconSide="right" | ||
onClick={() => setIsPlatformOptionsOpen(true)} | ||
> | ||
{PLATFORMS[currentPlatform]} | ||
</EuiButtonEmpty> | ||
} | ||
isOpen={isPlatformOptionsOpen} | ||
closePopover={() => setIsPlatformOptionsOpen(false)} | ||
> | ||
<EuiContextMenuPanel | ||
items={Object.entries(PLATFORMS).map(([platform, name]) => ( | ||
<EuiContextMenuItem | ||
key={platform} | ||
onClick={() => { | ||
setCurrentPlatform(platform as typeof currentPlatform); | ||
setIsPlatformOptionsOpen(false); | ||
}} | ||
> | ||
{name} | ||
</EuiContextMenuItem> | ||
))} | ||
/> | ||
</EuiPopover> | ||
} | ||
append={ | ||
<EuiCopy textToCopy={quickInstallInstructions}> | ||
{copy => ( | ||
<EuiButtonEmpty onClick={copy} color="primary" size="s"> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.copyInstructionsButtonText" | ||
defaultMessage="copy" | ||
/> | ||
</EuiButtonEmpty> | ||
)} | ||
</EuiCopy> | ||
} | ||
/> | ||
|
||
<EuiSpacer size="m" /> | ||
|
||
<EuiButtonEmpty | ||
onClick={() => setIsManualInstallationOpen(!isManualInstallationOpen)} | ||
iconType={isManualInstallationOpen ? 'arrowUp' : 'arrowDown'} | ||
iconSide="right" | ||
size="xs" | ||
flush="left" | ||
> | ||
<FormattedMessage | ||
id="xpack.fleet.agentEnrollment.manualInstructionsToggleLinkText" | ||
defaultMessage="Manual installation" | ||
/> | ||
</EuiButtonEmpty> | ||
|
||
{isManualInstallationOpen ? ( | ||
<Fragment> | ||
<EuiSpacer size="m" /> | ||
<ManualEnrollmentSteps | ||
instructions={PLATFORM_INSTRUCTIONS[currentPlatform] || PLATFORM_INSTRUCTIONS.macos} | ||
/> | ||
</Fragment> | ||
) : null} | ||
</Fragment> | ||
); | ||
}; |
Oops, something went wrong.