-
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.
* Interactive setup mode * remove first attempt * Added suggestions from code review * Verify CA before writing config * fix i18n path * updated plugin list * Updated page bundle limits * added manual configuration * fetch certificate chain * Fix race condition when calling multiple form methods * Fix i18n errors * added types and refactored slightly * welcome page styling * Remove holdsetup config option * typo * fix build errors * Updated manual configuration form * Remove issuer link * Add tests for decode enrollment token * Removed unused class names * fix issue where credentials got inherited from base config * Added tooltips and text overflow * styling fixes * refactored text truncate * Added unit tests * added suggestions from code review * Fixed typo and tests * Styling fixes * Fix i18n errors * Added suggestions from code review * Added route tests * Explicit type exports * Fix server url * Added unit tests * Added product not supported scenario
- Loading branch information
1 parent
234f7f6
commit 035937a
Showing
31 changed files
with
2,503 additions
and
84 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
.interactiveSetup { | ||
@include kibanaFullScreenGraphics; | ||
} | ||
|
||
.interactiveSetup__header { | ||
position: relative; | ||
z-index: 10; | ||
padding: $euiSizeXL; | ||
} | ||
|
||
.interactiveSetup__logo { | ||
@include kibanaCircleLogo; | ||
@include euiBottomShadowMedium; | ||
|
||
margin-bottom: $euiSizeXL; | ||
} | ||
|
||
.interactiveSetup__content { | ||
position: relative; | ||
z-index: 10; | ||
margin: auto; | ||
margin-bottom: $euiSizeXL; | ||
max-width: map-get($euiBreakpoints, 's') - $euiSizeXL; | ||
padding-left: $euiSizeXL; | ||
padding-right: $euiSizeXL; | ||
} |
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
70 changes: 70 additions & 0 deletions
70
src/plugins/interactive_setup/public/cluster_address_form.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,70 @@ | ||
/* | ||
* 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 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { fireEvent, render, waitFor } from '@testing-library/react'; | ||
import React from 'react'; | ||
|
||
import { coreMock } from 'src/core/public/mocks'; | ||
|
||
import { ClusterAddressForm } from './cluster_address_form'; | ||
import { Providers } from './plugin'; | ||
|
||
jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ | ||
htmlIdGenerator: () => () => `id-${Math.random()}`, | ||
})); | ||
|
||
describe('ClusterAddressForm', () => { | ||
jest.setTimeout(20_000); | ||
|
||
it('calls enrollment API when submitting form', async () => { | ||
const coreStart = coreMock.createStart(); | ||
coreStart.http.post.mockResolvedValue({}); | ||
|
||
const onSuccess = jest.fn(); | ||
|
||
const { findByRole, findByLabelText } = render( | ||
<Providers http={coreStart.http}> | ||
<ClusterAddressForm onSuccess={onSuccess} /> | ||
</Providers> | ||
); | ||
fireEvent.change(await findByLabelText('Address'), { | ||
target: { value: 'https://localhost' }, | ||
}); | ||
fireEvent.click(await findByRole('button', { name: 'Check address', hidden: true })); | ||
|
||
await waitFor(() => { | ||
expect(coreStart.http.post).toHaveBeenLastCalledWith('/internal/interactive_setup/ping', { | ||
body: JSON.stringify({ | ||
host: 'https://localhost:9200', | ||
}), | ||
}); | ||
expect(onSuccess).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
it('validates form', async () => { | ||
const coreStart = coreMock.createStart(); | ||
const onSuccess = jest.fn(); | ||
|
||
const { findAllByText, findByRole, findByLabelText } = render( | ||
<Providers http={coreStart.http}> | ||
<ClusterAddressForm onSuccess={onSuccess} /> | ||
</Providers> | ||
); | ||
|
||
fireEvent.change(await findByLabelText('Address'), { | ||
target: { value: 'localhost' }, | ||
}); | ||
|
||
fireEvent.click(await findByRole('button', { name: 'Check address', hidden: true })); | ||
|
||
await findAllByText(/Enter a valid address including protocol/i); | ||
|
||
expect(coreStart.http.post).not.toHaveBeenCalled(); | ||
}); | ||
}); |
146 changes: 146 additions & 0 deletions
146
src/plugins/interactive_setup/public/cluster_address_form.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,146 @@ | ||
/* | ||
* 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 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { | ||
EuiButton, | ||
EuiButtonEmpty, | ||
EuiCallOut, | ||
EuiFieldText, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
EuiForm, | ||
EuiFormRow, | ||
EuiSpacer, | ||
} from '@elastic/eui'; | ||
import type { FunctionComponent } from 'react'; | ||
import React from 'react'; | ||
|
||
import { i18n } from '@kbn/i18n'; | ||
import { FormattedMessage } from '@kbn/i18n/react'; | ||
import type { IHttpFetchError } from 'kibana/public'; | ||
|
||
import type { PingResult } from '../common'; | ||
import type { ValidationErrors } from './use_form'; | ||
import { useForm } from './use_form'; | ||
import { useHttp } from './use_http'; | ||
|
||
export interface ClusterAddressFormValues { | ||
host: string; | ||
} | ||
|
||
export interface ClusterAddressFormProps { | ||
defaultValues?: ClusterAddressFormValues; | ||
onCancel?(): void; | ||
onSuccess?(result: PingResult, values: ClusterAddressFormValues): void; | ||
} | ||
|
||
export const ClusterAddressForm: FunctionComponent<ClusterAddressFormProps> = ({ | ||
defaultValues = { | ||
host: 'https://localhost:9200', | ||
}, | ||
onCancel, | ||
onSuccess, | ||
}) => { | ||
const http = useHttp(); | ||
|
||
const [form, eventHandlers] = useForm({ | ||
defaultValues, | ||
validate: async (values) => { | ||
const errors: ValidationErrors<typeof values> = {}; | ||
|
||
if (!values.host) { | ||
errors.host = i18n.translate('interactiveSetup.clusterAddressForm.hostRequiredError', { | ||
defaultMessage: 'Enter an address.', | ||
}); | ||
} else { | ||
try { | ||
const url = new URL(values.host); | ||
if (!url.protocol || !url.hostname) { | ||
throw new Error(); | ||
} | ||
} catch (error) { | ||
errors.host = i18n.translate('interactiveSetup.clusterAddressForm.hostInvalidError', { | ||
defaultMessage: 'Enter a valid address including protocol.', | ||
}); | ||
} | ||
} | ||
|
||
return errors; | ||
}, | ||
onSubmit: async (values) => { | ||
const url = new URL(values.host); | ||
const host = `${url.protocol}//${url.hostname}:${url.port || 9200}`; | ||
|
||
const result = await http.post<PingResult>('/internal/interactive_setup/ping', { | ||
body: JSON.stringify({ host }), | ||
}); | ||
|
||
onSuccess?.(result, { host }); | ||
}, | ||
}); | ||
|
||
return ( | ||
<EuiForm component="form" noValidate {...eventHandlers}> | ||
{form.submitError && ( | ||
<> | ||
<EuiCallOut | ||
color="danger" | ||
title={i18n.translate('interactiveSetup.clusterAddressForm.submitErrorTitle', { | ||
defaultMessage: "Couldn't check address", | ||
})} | ||
> | ||
{(form.submitError as IHttpFetchError).body?.message} | ||
</EuiCallOut> | ||
<EuiSpacer /> | ||
</> | ||
)} | ||
|
||
<EuiFormRow | ||
label={i18n.translate('interactiveSetup.clusterAddressForm.hostLabel', { | ||
defaultMessage: 'Address', | ||
})} | ||
error={form.errors.host} | ||
isInvalid={form.touched.host && !!form.errors.host} | ||
fullWidth | ||
> | ||
<EuiFieldText | ||
name="host" | ||
value={form.values.host} | ||
isInvalid={form.touched.host && !!form.errors.host} | ||
fullWidth | ||
/> | ||
</EuiFormRow> | ||
<EuiSpacer /> | ||
|
||
<EuiFlexGroup responsive={false} justifyContent="flexEnd"> | ||
<EuiFlexItem grow={false}> | ||
<EuiButtonEmpty flush="right" iconType="arrowLeft" onClick={onCancel}> | ||
<FormattedMessage | ||
id="interactiveSetup.clusterAddressForm.cancelButton" | ||
defaultMessage="Back" | ||
/> | ||
</EuiButtonEmpty> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={false}> | ||
<EuiButton | ||
type="submit" | ||
isLoading={form.isSubmitting} | ||
isDisabled={form.isSubmitted && form.isInvalid} | ||
fill | ||
> | ||
<FormattedMessage | ||
id="interactiveSetup.clusterAddressForm.submitButton" | ||
defaultMessage="{isSubmitting, select, true{Checking address…} other{Check address}}" | ||
values={{ isSubmitting: form.isSubmitting }} | ||
/> | ||
</EuiButton> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiForm> | ||
); | ||
}; |
Oops, something went wrong.