Skip to content
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

[Ingest] Add Global settings flyout #64276

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions x-pack/plugins/ingest_manager/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './datasource';
export * from './epm';
export * from './output';
export * from './enrollment_api_key';
export * from './settings';
13 changes: 13 additions & 0 deletions x-pack/plugins/ingest_manager/common/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ export const AGENT_CONFIG_API_ROUTES = {
FULL_INFO_PATTERN: `${AGENT_CONFIG_API_ROOT}/{agentConfigId}/full`,
};

// Output API routes
export const OUTPUT_API_ROUTES = {
LIST_PATTERN: `${API_ROOT}/outputs`,
INFO_PATTERN: `${API_ROOT}/outputs/{outputId}`,
UPDATE_PATTERN: `${API_ROOT}/outputs/{outputId}`,
};

// Settings API routes
export const SETTINGS_API_ROUTES = {
INFO_PATTERN: `${API_ROOT}/settings`,
UPDATE_PATTERN: `${API_ROOT}/settings`,
};

// Agent API routes
export const AGENT_API_ROUTES = {
LIST_PATTERN: `${FLEET_API_ROOT}/agents`,
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/ingest_manager/common/constants/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* 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.
*/

export const GLOBAL_SETTINGS_SAVED_OBJECT_TYPE = 'ingest_manager_settings';
14 changes: 14 additions & 0 deletions x-pack/plugins/ingest_manager/common/services/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
AGENT_API_ROUTES,
ENROLLMENT_API_KEY_ROUTES,
SETUP_API_ROUTE,
OUTPUT_API_ROUTES,
SETTINGS_API_ROUTES,
} from '../constants';

export const epmRouteService = {
Expand Down Expand Up @@ -112,6 +114,18 @@ export const agentRouteService = {
getStatusPath: () => AGENT_API_ROUTES.STATUS_PATTERN,
};

export const outputRoutesService = {
getInfoPath: (outputId: string) => OUTPUT_API_ROUTES.INFO_PATTERN.replace('{outputId}', outputId),
getUpdatePath: (outputId: string) =>
OUTPUT_API_ROUTES.UPDATE_PATTERN.replace('{outputId}', outputId),
getListPath: () => OUTPUT_API_ROUTES.LIST_PATTERN,
};

export const settingsRoutesService = {
getInfoPath: () => SETTINGS_API_ROUTES.INFO_PATTERN,
getUpdatePath: () => SETTINGS_API_ROUTES.UPDATE_PATTERN,
};

export const enrollmentAPIKeyRouteService = {
getListPath: () => ENROLLMENT_API_KEY_ROUTES.LIST_PATTERN,
getCreatePath: () => ENROLLMENT_API_KEY_ROUTES.CREATE_PATTERN,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ingest_manager/common/types/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './data_stream';
export * from './output';
export * from './epm';
export * from './enrollment_api_key';
export * from './settings';
19 changes: 19 additions & 0 deletions x-pack/plugins/ingest_manager/common/types/models/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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 { SavedObjectAttributes } from 'src/core/public';

interface BaseSettings {
agent_auto_upgrade?: boolean;
package_auto_upgrade?: boolean;
kibana_url?: string;
kibana_ca_sha256?: string;
}

export interface Settings extends BaseSettings {
id: string;
}

export interface SettingsSOAttributes extends BaseSettings, SavedObjectAttributes {}
2 changes: 2 additions & 0 deletions x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ export * from './fleet_setup';
export * from './epm';
export * from './enrollment_api_key';
export * from './install_script';
export * from './output';
export * from './settings';
40 changes: 40 additions & 0 deletions x-pack/plugins/ingest_manager/common/types/rest_spec/output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 { Output } from '../models';

export interface GetOneOutputResponse {
item: Output;
success: boolean;
}

export interface GetOneOutputRequest {
params: {
outputId: string;
};
}

export interface PutOutputRequest {
params: {
outputId: string;
};
body: {
hosts?: string[];
ca_sha256?: string;
};
}

export interface PutOutputResponse {
item: Output;
success: boolean;
}

export interface GetOutputsResponse {
items: Output[];
total: number;
page: number;
perPage: number;
success: boolean;
}
20 changes: 20 additions & 0 deletions x-pack/plugins/ingest_manager/common/types/rest_spec/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 { Settings } from '../models';

export interface GetSettingsResponse {
item: Settings;
success: boolean;
}

export interface PutSettingsRequest {
body: Partial<Omit<Settings, 'id'>>;
}

export interface PutSettingsResponse {
item: Settings;
success: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export { Loading } from './loading';
export { Error } from './error';
export { Header, HeaderProps } from './header';
export { AlphaMessaging } from './alpha_messaging';
export * from './settings_flyout';
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/*
* 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, { useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutHeader,
EuiTitle,
EuiFlexGroup,
EuiFlexItem,
EuiButtonEmpty,
EuiSpacer,
EuiButton,
EuiFlyoutFooter,
EuiForm,
EuiFormRow,
EuiFieldText,
EuiRadioGroup,
EuiComboBox,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiText } from '@elastic/eui';
import { useInput, useComboInput, useCore, useGetSettings, sendPutSettings } from '../hooks';
import { useGetOutputs, sendPutOutput } from '../hooks/use_request/outputs';

interface Props {
onClose: () => void;
}

function useSettingsForm(outputId: string | undefined) {
const { notifications } = useCore();
const kibanaUrlInput = useInput();
const elasticsearchUrlInput = useComboInput([]);

return {
onSubmit: async () => {
try {
if (!outputId) {
throw new Error('Unable to load outputs');
}
await sendPutOutput(outputId, {
hosts: elasticsearchUrlInput.value,
});
await sendPutSettings({
kibana_url: kibanaUrlInput.value,
});
} catch (error) {
notifications.toasts.addError(error, {
title: 'Error',
});
}
notifications.toasts.addSuccess(
i18n.translate('xpack.ingestManager.settings.success.message', {
defaultMessage: 'Settings saved',
})
);
},
inputs: {
kibanaUrl: kibanaUrlInput,
elasticsearchUrl: elasticsearchUrlInput,
},
};
}

export const SettingFlyout: React.FunctionComponent<Props> = ({ onClose }) => {
const core = useCore();
const settingsRequest = useGetSettings();
const settings = settingsRequest?.data?.item;
const outputsRequest = useGetOutputs();
const output = outputsRequest.data?.items?.[0];
const { inputs, onSubmit } = useSettingsForm(output?.id);

useEffect(() => {
if (output) {
inputs.elasticsearchUrl.setValue(output.hosts || []);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [output]);

useEffect(() => {
if (settings) {
inputs.kibanaUrl.setValue(
settings.kibana_url || `${window.location.origin}${core.http.basePath.get()}`
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [settings]);

const body = (
<EuiForm>
<EuiRadioGroup
options={[
{
id: 'enabled',
label: i18n.translate('xpack.ingestManager.settings.autoUpgradeEnabledLabel', {
defaultMessage:
'Automatically update agent binaries to use the latest minor version.',
}),
},
{
id: 'disabled',
disabled: true,
label: i18n.translate('xpack.ingestManager.settings.autoUpgradeDisabledLabel', {
defaultMessage: 'Manually manage agent binary versions. Requires Gold license.',
}),
},
]}
idSelected={'enabled'}
onChange={id => {}}
legend={{
children: (
<EuiTitle size="xs">
<h3>
<FormattedMessage
id="xpack.ingestManager.settings.autoUpgradeFieldLabel"
defaultMessage="Elastic Agent binary version"
/>
</h3>
</EuiTitle>
),
}}
/>
<EuiSpacer size="l" />
<EuiRadioGroup
options={[
{
id: 'enabled',
label: i18n.translate(
'xpack.ingestManager.settings.integrationUpgradeEnabledFieldLabel',
{
defaultMessage:
'Automatically update Integrations to the latest version to receive the latest assets. Agent configurations may need to be updated in order to use new features.',
}
),
},
{
id: 'disabled',
disabled: true,
label: i18n.translate(
'xpack.ingestManager.settings.integrationUpgradeDisabledFieldLabel',
{
defaultMessage: 'Manually manage integration versions yourself.',
}
),
},
]}
idSelected={'enabled'}
onChange={id => {}}
legend={{
children: (
<EuiTitle size="xs">
<h3>
<FormattedMessage
id="xpack.ingestManager.settings.integrationUpgradeFieldLabel"
defaultMessage="Elastic integration version"
/>
</h3>
</EuiTitle>
),
}}
/>
<EuiSpacer size="l" />
<EuiTitle size="s">
<h3>
<FormattedMessage
id="xpack.ingestManager.settings.globalOutputTitle"
defaultMessage="Global output"
/>
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText color="subdued" size="s">
<FormattedMessage
id="xpack.ingestManager.settings.globalOutputDescription"
defaultMessage="The global output is applied to all agent configurations and specifies where data is sent."
/>
</EuiText>
<EuiSpacer size="m" />
<EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ingestManager.settings.kibanaUrlLabel', {
defaultMessage: 'Kibana URL',
})}
>
<EuiFieldText required={true} {...inputs.kibanaUrl.props} name="kibanaUrl" />
</EuiFormRow>
</EuiFormRow>
<EuiSpacer size="m" />
<EuiFormRow>
<EuiFormRow
label={i18n.translate('xpack.ingestManager.settings.elasticsearchUrlLabel', {
defaultMessage: 'Elasticsearch URL',
})}
>
<EuiComboBox noSuggestions {...inputs.elasticsearchUrl.props} />
</EuiFormRow>
</EuiFormRow>
</EuiForm>
);

return (
<EuiFlyout onClose={onClose} size="l" maxWidth={640}>
<EuiFlyoutHeader hasBorder aria-labelledby="IngestManagerSettingsFlyoutTitle">
<EuiTitle size="m">
<h2 id="IngestManagerSettingsFlyoutTitle">
<FormattedMessage
id="xpack.ingestManager.settings.flyoutTitle"
defaultMessage="Ingest Management settings"
/>
</h2>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>{body}</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButtonEmpty iconType="cross" onClick={onClose} flush="left">
<FormattedMessage
id="xpack.ingestManager.settings.cancelButtonLabel"
defaultMessage="Cancel"
/>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={onSubmit} iconType="save">
<FormattedMessage
id="xpack.ingestManager.settings.saveButtonLabel"
defaultMessage="Save settings"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutFooter>
</EuiFlyout>
);
};
Loading