[Upgrade Assistant] use request hook (#94473)
This commit is contained in:
parent
882248c671
commit
1592e3c01a
|
@ -32,3 +32,5 @@ export const indexSettingDeprecations = {
|
|||
settings: ['translog.retention.size', 'translog.retention.age'],
|
||||
},
|
||||
};
|
||||
|
||||
export const API_BASE_PATH = '/api/upgrade_assistant';
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
"ui": true,
|
||||
"configPath": ["xpack", "upgrade_assistant"],
|
||||
"requiredPlugins": ["management", "licensing", "features"],
|
||||
"optionalPlugins": ["cloud", "usageCollection"]
|
||||
"optionalPlugins": ["cloud", "usageCollection"],
|
||||
"requiredBundles": ["esUiShared"]
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { DocLinksStart, HttpSetup, NotificationsStart } from 'src/core/public';
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { ApiService } from './lib/api';
|
||||
|
||||
export interface KibanaVersionContext {
|
||||
currentMajor: number;
|
||||
|
@ -21,6 +22,7 @@ export interface ContextValue {
|
|||
kibanaVersionInfo: KibanaVersionContext;
|
||||
notifications: NotificationsStart;
|
||||
isReadOnlyMode: boolean;
|
||||
api: ApiService;
|
||||
}
|
||||
|
||||
export const AppContext = createContext<ContextValue>({} as any);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import React from 'react';
|
||||
|
||||
import { EuiCallOut } from '@elastic/eui';
|
||||
|
@ -16,7 +15,7 @@ import { UpgradeAssistantTabProps } from './types';
|
|||
export const LoadingErrorBanner: React.FunctionComponent<
|
||||
Pick<UpgradeAssistantTabProps, 'loadingError'>
|
||||
> = ({ loadingError }) => {
|
||||
if (get(loadingError, 'response.status') === 403) {
|
||||
if (loadingError?.statusCode === 403) {
|
||||
return (
|
||||
<EuiCallOut
|
||||
title={
|
||||
|
@ -27,6 +26,7 @@ export const LoadingErrorBanner: React.FunctionComponent<
|
|||
}
|
||||
color="danger"
|
||||
iconType="cross"
|
||||
data-test-subj="permissionsError"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ export const LoadingErrorBanner: React.FunctionComponent<
|
|||
}
|
||||
color="danger"
|
||||
iconType="cross"
|
||||
data-test-subj="upgradeStatusError"
|
||||
>
|
||||
{loadingError ? loadingError.message : null}
|
||||
</EuiCallOut>
|
||||
|
|
|
@ -14,7 +14,7 @@ import { ComingSoonPrompt } from './coming_soon_prompt';
|
|||
import { UpgradeAssistantTabs } from './tabs';
|
||||
|
||||
export const PageContent: React.FunctionComponent = () => {
|
||||
const { kibanaVersionInfo, isReadOnlyMode, http } = useAppContext();
|
||||
const { kibanaVersionInfo, isReadOnlyMode } = useAppContext();
|
||||
const { nextMajor } = kibanaVersionInfo;
|
||||
|
||||
// Read-only mode will be enabled up until the last minor before the next major release
|
||||
|
@ -38,7 +38,7 @@ export const PageContent: React.FunctionComponent = () => {
|
|||
</EuiPageHeaderSection>
|
||||
</EuiPageHeader>
|
||||
|
||||
<UpgradeAssistantTabs http={http} />
|
||||
<UpgradeAssistantTabs />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* 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 { mountWithIntl } from '@kbn/test/jest';
|
||||
import { httpServiceMock } from 'src/core/public/mocks';
|
||||
import { mockKibanaSemverVersion } from '../../../common/constants';
|
||||
import { UpgradeAssistantTabs } from './tabs';
|
||||
import { LoadingState } from './types';
|
||||
|
||||
import { OverviewTab } from './tabs/overview';
|
||||
|
||||
// Used to wait for promises to resolve and renders to finish before reading updates
|
||||
const promisesToResolve = () => new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
const mockHttp = httpServiceMock.createSetupContract();
|
||||
|
||||
jest.mock('../app_context', () => {
|
||||
return {
|
||||
useAppContext: () => {
|
||||
return {
|
||||
docLinks: {
|
||||
DOC_LINK_VERSION: 'current',
|
||||
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
|
||||
},
|
||||
kibanaVersionInfo: {
|
||||
currentMajor: mockKibanaSemverVersion.major,
|
||||
prevMajor: mockKibanaSemverVersion.major - 1,
|
||||
nextMajor: mockKibanaSemverVersion.major + 1,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('UpgradeAssistantTabs', () => {
|
||||
test('renders loading state', async () => {
|
||||
mockHttp.get.mockReturnValue(
|
||||
new Promise((resolve) => {
|
||||
/* never resolve */
|
||||
})
|
||||
);
|
||||
const wrapper = mountWithIntl(<UpgradeAssistantTabs http={mockHttp} />);
|
||||
// Should pass down loading status to child component
|
||||
expect(wrapper.find(OverviewTab).prop('loadingState')).toEqual(LoadingState.Loading);
|
||||
});
|
||||
|
||||
test('successful data fetch', async () => {
|
||||
// @ts-ignore
|
||||
mockHttp.get.mockResolvedValue({
|
||||
data: {
|
||||
cluster: [],
|
||||
indices: [],
|
||||
},
|
||||
});
|
||||
const wrapper = mountWithIntl(<UpgradeAssistantTabs http={mockHttp as any} />);
|
||||
expect(mockHttp.get).toHaveBeenCalled();
|
||||
await promisesToResolve();
|
||||
wrapper.update();
|
||||
// Should pass down success status to child component
|
||||
expect(wrapper.find(OverviewTab).prop('loadingState')).toEqual(LoadingState.Success);
|
||||
});
|
||||
|
||||
test('network failure', async () => {
|
||||
// @ts-ignore
|
||||
mockHttp.get.mockRejectedValue(new Error(`oh no!`));
|
||||
const wrapper = mountWithIntl(<UpgradeAssistantTabs http={mockHttp as any} />);
|
||||
await promisesToResolve();
|
||||
wrapper.update();
|
||||
// Should pass down error status to child component
|
||||
expect(wrapper.find(OverviewTab).prop('loadingState')).toEqual(LoadingState.Error);
|
||||
});
|
||||
|
||||
it('upgrade error', async () => {
|
||||
// @ts-ignore
|
||||
mockHttp.get.mockRejectedValue({ response: { status: 426 } });
|
||||
const wrapper = mountWithIntl(<UpgradeAssistantTabs http={mockHttp as any} />);
|
||||
await promisesToResolve();
|
||||
wrapper.update();
|
||||
// Should display an informative message if the cluster is currently mid-upgrade
|
||||
expect(wrapper.find('EuiEmptyPrompt').exists()).toBe(true);
|
||||
});
|
||||
});
|
|
@ -5,9 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { set } from '@elastic/safer-lodash-set';
|
||||
import { findIndex, get } from 'lodash';
|
||||
import React from 'react';
|
||||
import { findIndex } from 'lodash';
|
||||
import React, { useEffect, useState, useMemo } from 'react';
|
||||
|
||||
import {
|
||||
EuiEmptyPrompt,
|
||||
|
@ -18,173 +17,28 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { HttpSetup } from 'src/core/public';
|
||||
|
||||
import { UpgradeAssistantStatus } from '../../../common/types';
|
||||
import { LatestMinorBanner } from './latest_minor_banner';
|
||||
import { CheckupTab } from './tabs/checkup';
|
||||
import { OverviewTab } from './tabs/overview';
|
||||
import { LoadingState, TelemetryState, UpgradeAssistantTabProps } from './types';
|
||||
import { TelemetryState, UpgradeAssistantTabProps } from './types';
|
||||
import { useAppContext } from '../app_context';
|
||||
|
||||
enum ClusterUpgradeState {
|
||||
needsUpgrade,
|
||||
partiallyUpgraded,
|
||||
upgraded,
|
||||
}
|
||||
export const UpgradeAssistantTabs: React.FunctionComponent = () => {
|
||||
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
|
||||
const [telemetryState, setTelemetryState] = useState<TelemetryState>(TelemetryState.Complete);
|
||||
|
||||
interface TabsState {
|
||||
loadingState: LoadingState;
|
||||
loadingError?: Error;
|
||||
checkupData?: UpgradeAssistantStatus;
|
||||
selectedTabIndex: number;
|
||||
telemetryState: TelemetryState;
|
||||
clusterUpgradeState: ClusterUpgradeState;
|
||||
}
|
||||
const { api } = useAppContext();
|
||||
|
||||
interface Props {
|
||||
http: HttpSetup;
|
||||
}
|
||||
const { data: checkupData, isLoading, error, resendRequest } = api.useLoadUpgradeStatus();
|
||||
|
||||
export class UpgradeAssistantTabs extends React.Component<Props, TabsState> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
loadingState: LoadingState.Loading,
|
||||
clusterUpgradeState: ClusterUpgradeState.needsUpgrade,
|
||||
selectedTabIndex: 0,
|
||||
telemetryState: TelemetryState.Complete,
|
||||
};
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
await this.loadData();
|
||||
|
||||
// Send telemetry info about the default selected tab
|
||||
this.sendTelemetryInfo(this.tabs[this.state.selectedTabIndex].id);
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { selectedTabIndex, telemetryState, clusterUpgradeState } = this.state;
|
||||
const tabs = this.tabs;
|
||||
|
||||
if (clusterUpgradeState === ClusterUpgradeState.partiallyUpgraded) {
|
||||
return (
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<EuiEmptyPrompt
|
||||
iconType="logoElasticsearch"
|
||||
title={
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradingTitle"
|
||||
defaultMessage="Your cluster is upgrading"
|
||||
/>
|
||||
</h2>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradingDescription"
|
||||
defaultMessage="One or more Elasticsearch nodes have a newer version of
|
||||
Elasticsearch than Kibana. Once all your nodes are upgraded, upgrade Kibana."
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
);
|
||||
} else if (clusterUpgradeState === ClusterUpgradeState.upgraded) {
|
||||
return (
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<EuiEmptyPrompt
|
||||
iconType="logoElasticsearch"
|
||||
title={
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradeCompleteTitle"
|
||||
defaultMessage="Your cluster has been upgraded"
|
||||
/>
|
||||
</h2>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradeCompleteDescription"
|
||||
defaultMessage="All Elasticsearch nodes have been upgraded. You may now upgrade Kibana."
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiTabbedContent
|
||||
data-test-subj={
|
||||
telemetryState === TelemetryState.Running ? 'upgradeAssistantTelemetryRunning' : undefined
|
||||
}
|
||||
tabs={tabs}
|
||||
onTabClick={this.onTabClick}
|
||||
selectedTab={tabs[selectedTabIndex]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private onTabClick = (selectedTab: EuiTabbedContentTab) => {
|
||||
const selectedTabIndex = findIndex(this.tabs, { id: selectedTab.id });
|
||||
if (selectedTabIndex === -1) {
|
||||
throw new Error(`Clicked tab did not exist in tabs array`);
|
||||
}
|
||||
|
||||
// Send telemetry info about the current selected tab
|
||||
// only in case the clicked tab id it's different from the
|
||||
// current selected tab id
|
||||
if (this.tabs[this.state.selectedTabIndex].id !== selectedTab.id) {
|
||||
this.sendTelemetryInfo(selectedTab.id);
|
||||
}
|
||||
|
||||
this.setSelectedTabIndex(selectedTabIndex);
|
||||
};
|
||||
|
||||
private setSelectedTabIndex = (selectedTabIndex: number) => {
|
||||
this.setState({ selectedTabIndex });
|
||||
};
|
||||
|
||||
private loadData = async () => {
|
||||
try {
|
||||
this.setState({ loadingState: LoadingState.Loading });
|
||||
const resp = await this.props.http.get('/api/upgrade_assistant/status');
|
||||
this.setState({
|
||||
loadingState: LoadingState.Success,
|
||||
// resp.data is specifically to handle the CITs which uses axios to mock HTTP requests
|
||||
checkupData: resp.data ? resp.data : resp,
|
||||
});
|
||||
} catch (e) {
|
||||
if (get(e, 'response.status') === 426) {
|
||||
this.setState({
|
||||
loadingState: LoadingState.Success,
|
||||
clusterUpgradeState: get(e, 'response.data.attributes.allNodesUpgraded', false)
|
||||
? ClusterUpgradeState.upgraded
|
||||
: ClusterUpgradeState.partiallyUpgraded,
|
||||
});
|
||||
} else {
|
||||
this.setState({ loadingState: LoadingState.Error, loadingError: e });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private get tabs() {
|
||||
const { loadingError, loadingState, checkupData } = this.state;
|
||||
const commonProps: UpgradeAssistantTabProps = {
|
||||
loadingError,
|
||||
loadingState,
|
||||
refreshCheckupData: this.loadData,
|
||||
setSelectedTabIndex: this.setSelectedTabIndex,
|
||||
// Remove this in last minor of the current major (eg. 6.7)
|
||||
const tabs = useMemo(() => {
|
||||
const commonTabProps: UpgradeAssistantTabProps = {
|
||||
loadingError: error,
|
||||
isLoading,
|
||||
refreshCheckupData: resendRequest,
|
||||
setSelectedTabIndex,
|
||||
// Remove this in last minor of the current major (e.g., 7.15)
|
||||
alertBanner: <LatestMinorBanner />,
|
||||
};
|
||||
|
||||
|
@ -195,7 +49,7 @@ export class UpgradeAssistantTabs extends React.Component<Props, TabsState> {
|
|||
name: i18n.translate('xpack.upgradeAssistant.overviewTab.overviewTabTitle', {
|
||||
defaultMessage: 'Overview',
|
||||
}),
|
||||
content: <OverviewTab checkupData={checkupData} {...commonProps} />,
|
||||
content: <OverviewTab checkupData={checkupData} {...commonTabProps} />,
|
||||
},
|
||||
{
|
||||
id: 'cluster',
|
||||
|
@ -210,7 +64,7 @@ export class UpgradeAssistantTabs extends React.Component<Props, TabsState> {
|
|||
checkupLabel={i18n.translate('xpack.upgradeAssistant.tabs.checkupTab.clusterLabel', {
|
||||
defaultMessage: 'cluster',
|
||||
})}
|
||||
{...commonProps}
|
||||
{...commonTabProps}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -228,26 +82,103 @@ export class UpgradeAssistantTabs extends React.Component<Props, TabsState> {
|
|||
defaultMessage: 'index',
|
||||
})}
|
||||
showBackupWarning
|
||||
{...commonProps}
|
||||
{...commonTabProps}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
}, [checkupData, error, isLoading, resendRequest]);
|
||||
|
||||
private async sendTelemetryInfo(tabName: string) {
|
||||
// In case we don't have any data yet, we wanna to ignore the
|
||||
// telemetry info update
|
||||
if (this.state.loadingState !== LoadingState.Success) {
|
||||
return;
|
||||
const tabName = tabs[selectedTabIndex].id;
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoading === false) {
|
||||
setTelemetryState(TelemetryState.Running);
|
||||
|
||||
async function sendTelemetryData() {
|
||||
await api.sendTelemetryData({
|
||||
[tabName]: true,
|
||||
});
|
||||
setTelemetryState(TelemetryState.Complete);
|
||||
}
|
||||
|
||||
sendTelemetryData();
|
||||
}
|
||||
}, [api, selectedTabIndex, tabName, isLoading]);
|
||||
|
||||
this.setState({ telemetryState: TelemetryState.Running });
|
||||
const onTabClick = (selectedTab: EuiTabbedContentTab) => {
|
||||
const newSelectedTabIndex = findIndex(tabs, { id: selectedTab.id });
|
||||
if (selectedTabIndex === -1) {
|
||||
throw new Error('Clicked tab did not exist in tabs array');
|
||||
}
|
||||
setSelectedTabIndex(newSelectedTabIndex);
|
||||
};
|
||||
|
||||
await this.props.http.put('/api/upgrade_assistant/stats/ui_open', {
|
||||
body: JSON.stringify(set({}, tabName, true)),
|
||||
});
|
||||
|
||||
this.setState({ telemetryState: TelemetryState.Complete });
|
||||
if (error?.statusCode === 426 && error.attributes?.allNodesUpgraded === false) {
|
||||
return (
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<EuiEmptyPrompt
|
||||
iconType="logoElasticsearch"
|
||||
data-test-subj="partiallyUpgradedPrompt"
|
||||
title={
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradingTitle"
|
||||
defaultMessage="Your cluster is upgrading"
|
||||
/>
|
||||
</h2>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradingDescription"
|
||||
defaultMessage="One or more Elasticsearch nodes have a newer version of
|
||||
Elasticsearch than Kibana. Once all your nodes are upgraded, upgrade Kibana."
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
);
|
||||
} else if (error?.statusCode === 426 && error.attributes?.allNodesUpgraded === true) {
|
||||
return (
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<EuiEmptyPrompt
|
||||
iconType="logoElasticsearch"
|
||||
data-test-subj="upgradedPrompt"
|
||||
title={
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradeCompleteTitle"
|
||||
defaultMessage="Your cluster has been upgraded"
|
||||
/>
|
||||
</h2>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradeCompleteDescription"
|
||||
defaultMessage="All Elasticsearch nodes have been upgraded. You may now upgrade Kibana."
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiTabbedContent
|
||||
data-test-subj={
|
||||
telemetryState === TelemetryState.Running ? 'upgradeAssistantTelemetryRunning' : undefined
|
||||
}
|
||||
tabs={tabs}
|
||||
onTabClick={onTabClick}
|
||||
selectedTab={tabs[selectedTabIndex]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,472 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CheckupTab render with deprecations 1`] = `
|
||||
<Fragment>
|
||||
<EuiSpacer />
|
||||
<EuiText
|
||||
grow={false}
|
||||
>
|
||||
<p
|
||||
data-test-subj="upgradeAssistantIndexTabDetail"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="These {strongCheckupLabel} issues need your attention. Resolve them before upgrading to Elasticsearch {nextEsVersion}."
|
||||
id="xpack.upgradeAssistant.checkupTab.tabDetail"
|
||||
values={
|
||||
Object {
|
||||
"nextEsVersion": "9.x",
|
||||
"strongCheckupLabel": <strong>
|
||||
index
|
||||
</strong>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Back up your indices now"
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Back up your data using the {snapshotRestoreDocsButton}."
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutBody.calloutDetail"
|
||||
values={
|
||||
Object {
|
||||
"snapshotRestoreDocsButton": <EuiLink
|
||||
external={true}
|
||||
href="https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="snapshot and restore APIs"
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutBody.snapshotRestoreDocsButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer />
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<div
|
||||
data-test-subj="deprecationsContainer"
|
||||
>
|
||||
<CheckupControls
|
||||
allDeprecations={
|
||||
Array [
|
||||
Object {
|
||||
"details": "[[type: doc, field: spins], [type: doc, field: mlockall], [type: doc, field: node_master], [type: doc, field: primary]]",
|
||||
"index": ".monitoring-es-6-2018.11.07",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: tweet, field: liked]]",
|
||||
"index": "twitter",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: index-pattern, field: notExpandable], [type: config, field: xPackMonitoring:allowReport], [type: config, field: xPackMonitoring:showBanner], [type: dashboard, field: pause], [type: dashboard, field: timeRestore]]",
|
||||
"index": ".kibana",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: doc, field: notify], [type: doc, field: created], [type: doc, field: attach_payload], [type: doc, field: met]]",
|
||||
"index": ".watcher-history-6-2018.11.07",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: doc, field: snapshot]]",
|
||||
"index": ".monitoring-kibana-6-2018.11.07",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: tweet, field: liked]]",
|
||||
"index": "twitter2",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"label": "Reindex in Console",
|
||||
"url": "/app/dev_tools#/console?load_from=%2Fapi%2Fupgrade_assistant%2Freindex%2Fconsole_template%2Ftwitter.json",
|
||||
},
|
||||
],
|
||||
"details": "Reindexing is irreversible, so always back up your index before proceeding.",
|
||||
"index": "twitter",
|
||||
"level": "critical",
|
||||
"message": "This index must be reindexed in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/reindex-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"details": "Upgrading is irreversible, so always back up your index before proceeding.",
|
||||
"index": ".triggered_watches",
|
||||
"level": "critical",
|
||||
"message": "This index must be upgraded in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"label": "Reindex in Console",
|
||||
"url": "/app/dev_tools#/console?load_from=%2Fapi%2Fupgrade_assistant%2Freindex%2Fconsole_template%2F.reindex-status.json",
|
||||
},
|
||||
],
|
||||
"details": "Reindexing is irreversible, so always back up your index before proceeding.",
|
||||
"index": ".reindex-status",
|
||||
"level": "critical",
|
||||
"message": "This index must be reindexed in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/reindex-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"label": "Reindex in Console",
|
||||
"url": "/app/dev_tools#/console?load_from=%2Fapi%2Fupgrade_assistant%2Freindex%2Fconsole_template%2Ftwitter2.json",
|
||||
},
|
||||
],
|
||||
"details": "Reindexing is irreversible, so always back up your index before proceeding.",
|
||||
"index": "twitter2",
|
||||
"level": "critical",
|
||||
"message": "This index must be reindexed in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/reindex-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"details": "Upgrading is irreversible, so always back up your index before proceeding.",
|
||||
"index": ".watches",
|
||||
"level": "critical",
|
||||
"message": "This index must be upgraded in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-upgrade.html",
|
||||
},
|
||||
]
|
||||
}
|
||||
availableGroupByOptions={
|
||||
Array [
|
||||
"message",
|
||||
"index",
|
||||
]
|
||||
}
|
||||
currentFilter="all"
|
||||
currentGroupBy="message"
|
||||
loadData={[MockFunction]}
|
||||
loadingState={1}
|
||||
onFilterChange={[Function]}
|
||||
onGroupByChange={[Function]}
|
||||
onSearchChange={[Function]}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<GroupedDeprecations
|
||||
allDeprecations={
|
||||
Array [
|
||||
Object {
|
||||
"details": "[[type: doc, field: spins], [type: doc, field: mlockall], [type: doc, field: node_master], [type: doc, field: primary]]",
|
||||
"index": ".monitoring-es-6-2018.11.07",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: tweet, field: liked]]",
|
||||
"index": "twitter",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: index-pattern, field: notExpandable], [type: config, field: xPackMonitoring:allowReport], [type: config, field: xPackMonitoring:showBanner], [type: dashboard, field: pause], [type: dashboard, field: timeRestore]]",
|
||||
"index": ".kibana",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: doc, field: notify], [type: doc, field: created], [type: doc, field: attach_payload], [type: doc, field: met]]",
|
||||
"index": ".watcher-history-6-2018.11.07",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: doc, field: snapshot]]",
|
||||
"index": ".monitoring-kibana-6-2018.11.07",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"details": "[[type: tweet, field: liked]]",
|
||||
"index": "twitter2",
|
||||
"level": "warning",
|
||||
"message": "Coercion of boolean fields",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"label": "Reindex in Console",
|
||||
"url": "/app/dev_tools#/console?load_from=%2Fapi%2Fupgrade_assistant%2Freindex%2Fconsole_template%2Ftwitter.json",
|
||||
},
|
||||
],
|
||||
"details": "Reindexing is irreversible, so always back up your index before proceeding.",
|
||||
"index": "twitter",
|
||||
"level": "critical",
|
||||
"message": "This index must be reindexed in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/reindex-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"details": "Upgrading is irreversible, so always back up your index before proceeding.",
|
||||
"index": ".triggered_watches",
|
||||
"level": "critical",
|
||||
"message": "This index must be upgraded in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"label": "Reindex in Console",
|
||||
"url": "/app/dev_tools#/console?load_from=%2Fapi%2Fupgrade_assistant%2Freindex%2Fconsole_template%2F.reindex-status.json",
|
||||
},
|
||||
],
|
||||
"details": "Reindexing is irreversible, so always back up your index before proceeding.",
|
||||
"index": ".reindex-status",
|
||||
"level": "critical",
|
||||
"message": "This index must be reindexed in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/reindex-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"actions": Array [
|
||||
Object {
|
||||
"label": "Reindex in Console",
|
||||
"url": "/app/dev_tools#/console?load_from=%2Fapi%2Fupgrade_assistant%2Freindex%2Fconsole_template%2Ftwitter2.json",
|
||||
},
|
||||
],
|
||||
"details": "Reindexing is irreversible, so always back up your index before proceeding.",
|
||||
"index": "twitter2",
|
||||
"level": "critical",
|
||||
"message": "This index must be reindexed in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/reindex-upgrade.html",
|
||||
},
|
||||
Object {
|
||||
"details": "Upgrading is irreversible, so always back up your index before proceeding.",
|
||||
"index": ".watches",
|
||||
"level": "critical",
|
||||
"message": "This index must be upgraded in order to upgrade the Elastic Stack.",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-upgrade.html",
|
||||
},
|
||||
]
|
||||
}
|
||||
currentFilter="all"
|
||||
currentGroupBy="message"
|
||||
search=""
|
||||
/>
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`CheckupTab render with error 1`] = `
|
||||
<Fragment>
|
||||
<EuiSpacer />
|
||||
<EuiText
|
||||
grow={false}
|
||||
>
|
||||
<p
|
||||
data-test-subj="upgradeAssistantIndexTabDetail"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="These {strongCheckupLabel} issues need your attention. Resolve them before upgrading to Elasticsearch {nextEsVersion}."
|
||||
id="xpack.upgradeAssistant.checkupTab.tabDetail"
|
||||
values={
|
||||
Object {
|
||||
"nextEsVersion": "9.x",
|
||||
"strongCheckupLabel": <strong>
|
||||
index
|
||||
</strong>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Back up your indices now"
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Back up your data using the {snapshotRestoreDocsButton}."
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutBody.calloutDetail"
|
||||
values={
|
||||
Object {
|
||||
"snapshotRestoreDocsButton": <EuiLink
|
||||
external={true}
|
||||
href="https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="snapshot and restore APIs"
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutBody.snapshotRestoreDocsButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer />
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<LoadingErrorBanner
|
||||
loadingError={[Error: something bad!]}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`CheckupTab render without deprecations 1`] = `
|
||||
<Fragment>
|
||||
<EuiSpacer />
|
||||
<EuiText
|
||||
grow={false}
|
||||
>
|
||||
<p
|
||||
data-test-subj="upgradeAssistantIndexTabDetail"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="These {strongCheckupLabel} issues need your attention. Resolve them before upgrading to Elasticsearch {nextEsVersion}."
|
||||
id="xpack.upgradeAssistant.checkupTab.tabDetail"
|
||||
values={
|
||||
Object {
|
||||
"nextEsVersion": "9.x",
|
||||
"strongCheckupLabel": <strong>
|
||||
index
|
||||
</strong>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Back up your indices now"
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Back up your data using the {snapshotRestoreDocsButton}."
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutBody.calloutDetail"
|
||||
values={
|
||||
Object {
|
||||
"snapshotRestoreDocsButton": <EuiLink
|
||||
external={true}
|
||||
href="https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="snapshot and restore APIs"
|
||||
id="xpack.upgradeAssistant.checkupTab.backUpCallout.calloutBody.snapshotRestoreDocsButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer />
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
<EuiEmptyPrompt
|
||||
body={
|
||||
<React.Fragment>
|
||||
<p
|
||||
data-test-subj="upgradeAssistantIssueSummary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="You have no {strongCheckupLabel} issues."
|
||||
id="xpack.upgradeAssistant.checkupTab.noIssues.noIssuesLabel"
|
||||
values={
|
||||
Object {
|
||||
"strongCheckupLabel": <strong>
|
||||
index
|
||||
</strong>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Check the {overviewTabButton} for next steps."
|
||||
id="xpack.upgradeAssistant.checkupTab.noIssues.nextStepsDetail"
|
||||
values={
|
||||
Object {
|
||||
"overviewTabButton": <EuiLink
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Overview tab"
|
||||
id="xpack.upgradeAssistant.checkupTab.noIssues.nextStepsDetail.overviewTabButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</React.Fragment>
|
||||
}
|
||||
iconType="faceHappy"
|
||||
title={
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
defaultMessage="All clear!"
|
||||
id="xpack.upgradeAssistant.checkupTab.noIssues.noIssuesTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h2>
|
||||
}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</Fragment>
|
||||
`;
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* 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 { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { mockKibanaSemverVersion } from '../../../../../common/constants';
|
||||
|
||||
import { LoadingState } from '../../types';
|
||||
import AssistanceData from '../__fixtures__/checkup_api_response.json';
|
||||
import { CheckupTab } from './checkup_tab';
|
||||
|
||||
const defaultProps = {
|
||||
checkupLabel: 'index',
|
||||
deprecations: AssistanceData.indices,
|
||||
showBackupWarning: true,
|
||||
refreshCheckupData: jest.fn(),
|
||||
loadingState: LoadingState.Success,
|
||||
setSelectedTabIndex: jest.fn(),
|
||||
};
|
||||
|
||||
jest.mock('../../../app_context', () => {
|
||||
return {
|
||||
useAppContext: () => {
|
||||
return {
|
||||
docLinks: {
|
||||
DOC_LINK_VERSION: 'current',
|
||||
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
|
||||
},
|
||||
kibanaVersionInfo: {
|
||||
currentMajor: mockKibanaSemverVersion.major,
|
||||
prevMajor: mockKibanaSemverVersion.major - 1,
|
||||
nextMajor: mockKibanaSemverVersion.major + 1,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Mostly a dumb container with copy, test the three main states.
|
||||
*/
|
||||
describe('CheckupTab', () => {
|
||||
test('render with deprecations', () => {
|
||||
// @ts-expect-error mock data is too loosely typed
|
||||
expect(shallow(<CheckupTab {...defaultProps} />)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('render without deprecations', () => {
|
||||
expect(
|
||||
shallow(
|
||||
<CheckupTab
|
||||
{...{ ...defaultProps, deprecations: undefined, loadingState: LoadingState.Loading }}
|
||||
/>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('render with error', () => {
|
||||
expect(
|
||||
shallow(
|
||||
<CheckupTab
|
||||
{...{
|
||||
...defaultProps,
|
||||
deprecations: undefined,
|
||||
loadingState: LoadingState.Error,
|
||||
loadingError: new Error('something bad!'),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -21,12 +21,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
|
||||
import { LoadingErrorBanner } from '../../error_banner';
|
||||
import { useAppContext } from '../../../app_context';
|
||||
import {
|
||||
GroupByOption,
|
||||
LevelFilterOption,
|
||||
LoadingState,
|
||||
UpgradeAssistantTabProps,
|
||||
} from '../../types';
|
||||
import { GroupByOption, LevelFilterOption, UpgradeAssistantTabProps } from '../../types';
|
||||
import { CheckupControls } from './controls';
|
||||
import { GroupedDeprecations } from './deprecations/grouped';
|
||||
|
||||
|
@ -44,7 +39,7 @@ export const CheckupTab: FunctionComponent<CheckupTabProps> = ({
|
|||
checkupLabel,
|
||||
deprecations,
|
||||
loadingError,
|
||||
loadingState,
|
||||
isLoading,
|
||||
refreshCheckupData,
|
||||
setSelectedTabIndex,
|
||||
showBackupWarning = false,
|
||||
|
@ -159,13 +154,13 @@ export const CheckupTab: FunctionComponent<CheckupTabProps> = ({
|
|||
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
{loadingState === LoadingState.Error ? (
|
||||
{loadingError ? (
|
||||
<LoadingErrorBanner loadingError={loadingError} />
|
||||
) : deprecations && deprecations.length > 0 ? (
|
||||
<div data-test-subj="deprecationsContainer">
|
||||
<CheckupControls
|
||||
allDeprecations={deprecations}
|
||||
loadingState={loadingState}
|
||||
isLoading={isLoading}
|
||||
loadData={refreshCheckupData}
|
||||
currentFilter={currentFilter}
|
||||
onFilterChange={changeFilter}
|
||||
|
@ -180,6 +175,7 @@ export const CheckupTab: FunctionComponent<CheckupTabProps> = ({
|
|||
) : (
|
||||
<EuiEmptyPrompt
|
||||
iconType="faceHappy"
|
||||
data-test-subj="noDeprecationsPrompt"
|
||||
title={
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { EuiButton, EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { DeprecationInfo } from '../../../../../common/types';
|
||||
import { GroupByOption, LevelFilterOption, LoadingState } from '../../types';
|
||||
import { GroupByOption, LevelFilterOption } from '../../types';
|
||||
import { FilterBar } from './filter_bar';
|
||||
import { GroupByBar } from './group_by_bar';
|
||||
|
||||
|
@ -18,7 +18,7 @@ import { validateRegExpString } from '../../../utils';
|
|||
|
||||
interface CheckupControlsProps {
|
||||
allDeprecations?: DeprecationInfo[];
|
||||
loadingState: LoadingState;
|
||||
isLoading: boolean;
|
||||
loadData: () => void;
|
||||
currentFilter: LevelFilterOption;
|
||||
onFilterChange: (filter: LevelFilterOption) => void;
|
||||
|
@ -30,7 +30,7 @@ interface CheckupControlsProps {
|
|||
|
||||
export const CheckupControls: FunctionComponent<CheckupControlsProps> = ({
|
||||
allDeprecations,
|
||||
loadingState,
|
||||
isLoading,
|
||||
loadData,
|
||||
currentFilter,
|
||||
onFilterChange,
|
||||
|
@ -80,12 +80,7 @@ export const CheckupControls: FunctionComponent<CheckupControlsProps> = ({
|
|||
<GroupByBar {...{ availableGroupByOptions, currentGroupBy, onGroupByChange }} />
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
fill
|
||||
onClick={loadData}
|
||||
iconType="refresh"
|
||||
isLoading={loadingState === LoadingState.Loading}
|
||||
>
|
||||
<EuiButton fill onClick={loadData} iconType="refresh" isLoading={isLoading}>
|
||||
<FormattedMessage
|
||||
id="xpack.upgradeAssistant.checkupTab.controls.refreshButtonLabel"
|
||||
defaultMessage="Refresh"
|
||||
|
|
|
@ -58,29 +58,23 @@ export const RemoveIndexSettingsProvider = ({ children }: Props) => {
|
|||
const deprecatedSettings = useRef<string[]>([]);
|
||||
const indexName = useRef<string | undefined>(undefined);
|
||||
|
||||
const { http, notifications } = useAppContext();
|
||||
const { api, notifications } = useAppContext();
|
||||
|
||||
const removeIndexSettings = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await http.post(`/api/upgrade_assistant/${indexName.current}/index_settings`, {
|
||||
body: JSON.stringify({
|
||||
settings: deprecatedSettings.current,
|
||||
}),
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
const { error } = await api.updateIndexSettings(indexName.current!, deprecatedSettings.current);
|
||||
|
||||
setIsLoading(false);
|
||||
closeModal();
|
||||
|
||||
if (error) {
|
||||
notifications.toasts.addDanger(i18nTexts.errorNotificationText);
|
||||
} else {
|
||||
setSuccessfulRequests({
|
||||
[indexName.current!]: true,
|
||||
});
|
||||
closeModal();
|
||||
notifications.toasts.addSuccess(i18nTexts.successNotificationText);
|
||||
} catch (e) {
|
||||
setIsLoading(false);
|
||||
closeModal();
|
||||
notifications.toasts.addError(e, {
|
||||
title: i18nTexts.errorNotificationText,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import { Subscription } from 'rxjs';
|
|||
import { EuiButton, EuiLoadingSpinner, EuiText, EuiToolTip } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { DocLinksStart, HttpSetup } from 'src/core/public';
|
||||
import { API_BASE_PATH } from '../../../../../../../common/constants';
|
||||
import {
|
||||
EnrichedDeprecationInfo,
|
||||
ReindexStatus,
|
||||
|
@ -240,7 +241,7 @@ export class ReindexButton extends React.Component<ReindexButtonProps, ReindexBu
|
|||
};
|
||||
|
||||
private async sendUIReindexTelemetryInfo(uiReindexAction: UIReindexOption) {
|
||||
await this.props.http.put('/api/upgrade_assistant/stats/ui_reindex', {
|
||||
await this.props.http.put(`${API_BASE_PATH}/stats/ui_reindex`, {
|
||||
body: JSON.stringify(set({}, uiReindexAction, true)),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
import { HttpSetup } from 'src/core/public';
|
||||
import { API_BASE_PATH } from '../../../../../../../common/constants';
|
||||
import {
|
||||
IndexGroup,
|
||||
ReindexOperation,
|
||||
|
@ -60,7 +61,7 @@ export class ReindexPollingService {
|
|||
|
||||
try {
|
||||
const data = await this.http.get<StatusResponse>(
|
||||
`/api/upgrade_assistant/reindex/${this.indexName}`
|
||||
`${API_BASE_PATH}/reindex/${this.indexName}`
|
||||
);
|
||||
this.updateWithResponse(data);
|
||||
|
||||
|
@ -98,7 +99,7 @@ export class ReindexPollingService {
|
|||
});
|
||||
|
||||
const data = await this.http.post<ReindexOperation>(
|
||||
`/api/upgrade_assistant/reindex/${this.indexName}`
|
||||
`${API_BASE_PATH}/reindex/${this.indexName}`
|
||||
);
|
||||
|
||||
this.updateWithResponse({ reindexOp: data });
|
||||
|
@ -115,7 +116,7 @@ export class ReindexPollingService {
|
|||
cancelLoadingState: LoadingState.Loading,
|
||||
});
|
||||
|
||||
await this.http.post(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`);
|
||||
await this.http.post(`${API_BASE_PATH}/reindex/${this.indexName}/cancel`);
|
||||
} catch (e) {
|
||||
this.status$.next({
|
||||
...this.status$.value,
|
||||
|
|
|
@ -5,71 +5,52 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { EuiLoadingSpinner, EuiSwitch } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { HttpSetup } from 'src/core/public';
|
||||
import { useAppContext } from '../../../app_context';
|
||||
import { ResponseError } from '../../../lib/api';
|
||||
|
||||
import { LoadingState } from '../../types';
|
||||
export const DeprecationLoggingToggle: React.FunctionComponent = () => {
|
||||
const { api } = useAppContext();
|
||||
|
||||
interface DeprecationLoggingTabProps {
|
||||
http: HttpSetup;
|
||||
}
|
||||
const [isEnabled, setIsEnabled] = useState(true);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<ResponseError | undefined>(undefined);
|
||||
|
||||
interface DeprecationLoggingTabState {
|
||||
loadingState: LoadingState;
|
||||
loggingEnabled?: boolean;
|
||||
}
|
||||
useEffect(() => {
|
||||
async function getDeprecationLoggingStatus() {
|
||||
setIsLoading(true);
|
||||
|
||||
export class DeprecationLoggingToggle extends React.Component<
|
||||
DeprecationLoggingTabProps,
|
||||
DeprecationLoggingTabState
|
||||
> {
|
||||
constructor(props: DeprecationLoggingTabProps) {
|
||||
super(props);
|
||||
const { data, error: responseError } = await api.getDeprecationLogging();
|
||||
|
||||
this.state = {
|
||||
loadingState: LoadingState.Loading,
|
||||
};
|
||||
}
|
||||
setIsLoading(false);
|
||||
|
||||
public UNSAFE_componentWillMount() {
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { loggingEnabled, loadingState } = this.state;
|
||||
|
||||
// Show a spinner until we've done the initial load.
|
||||
if (loadingState === LoadingState.Loading && loggingEnabled === undefined) {
|
||||
return <EuiLoadingSpinner size="l" />;
|
||||
if (responseError) {
|
||||
setError(responseError);
|
||||
} else if (data) {
|
||||
setIsEnabled(data.isEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiSwitch
|
||||
id="xpack.upgradeAssistant.overviewTab.steps.deprecationLogsStep.enableDeprecationLoggingToggleSwitch"
|
||||
data-test-subj="upgradeAssistantDeprecationToggle"
|
||||
label={this.renderLoggingState()}
|
||||
checked={loggingEnabled || false}
|
||||
onChange={this.toggleLogging}
|
||||
disabled={loadingState === LoadingState.Loading || loadingState === LoadingState.Error}
|
||||
/>
|
||||
);
|
||||
getDeprecationLoggingStatus();
|
||||
}, [api]);
|
||||
|
||||
if (isLoading) {
|
||||
return <EuiLoadingSpinner size="l" />;
|
||||
}
|
||||
|
||||
private renderLoggingState() {
|
||||
const { loggingEnabled, loadingState } = this.state;
|
||||
|
||||
if (loadingState === LoadingState.Error) {
|
||||
const renderLoggingState = () => {
|
||||
if (error) {
|
||||
return i18n.translate(
|
||||
'xpack.upgradeAssistant.overviewTab.steps.deprecationLogsStep.enableDeprecationLoggingToggleSwitch.errorLabel',
|
||||
{
|
||||
defaultMessage: 'Could not load logging state',
|
||||
}
|
||||
);
|
||||
} else if (loggingEnabled) {
|
||||
} else if (isEnabled) {
|
||||
return i18n.translate(
|
||||
'xpack.upgradeAssistant.overviewTab.steps.deprecationLogsStep.enableDeprecationLoggingToggleSwitch.enabledLabel',
|
||||
{
|
||||
|
@ -84,39 +65,33 @@ export class DeprecationLoggingToggle extends React.Component<
|
|||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private loadData = async () => {
|
||||
try {
|
||||
this.setState({ loadingState: LoadingState.Loading });
|
||||
const resp = await this.props.http.get('/api/upgrade_assistant/deprecation_logging');
|
||||
this.setState({
|
||||
loadingState: LoadingState.Success,
|
||||
loggingEnabled: resp.isEnabled,
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState({ loadingState: LoadingState.Error });
|
||||
const toggleLogging = async () => {
|
||||
const newIsEnabledValue = !isEnabled;
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const { data, error: updateError } = await api.updateDeprecationLogging({
|
||||
isEnabled: newIsEnabledValue,
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
|
||||
if (updateError) {
|
||||
setError(updateError);
|
||||
} else if (data) {
|
||||
setIsEnabled(data.isEnabled);
|
||||
}
|
||||
};
|
||||
|
||||
private toggleLogging = async () => {
|
||||
try {
|
||||
// Optimistically toggle the UI
|
||||
const newEnabled = !this.state.loggingEnabled;
|
||||
this.setState({ loadingState: LoadingState.Loading, loggingEnabled: newEnabled });
|
||||
|
||||
const resp = await this.props.http.put('/api/upgrade_assistant/deprecation_logging', {
|
||||
body: JSON.stringify({
|
||||
isEnabled: newEnabled,
|
||||
}),
|
||||
});
|
||||
|
||||
this.setState({
|
||||
loadingState: LoadingState.Success,
|
||||
loggingEnabled: resp.isEnabled,
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState({ loadingState: LoadingState.Error });
|
||||
}
|
||||
};
|
||||
}
|
||||
return (
|
||||
<EuiSwitch
|
||||
data-test-subj="upgradeAssistantDeprecationToggle"
|
||||
label={renderLoggingState()}
|
||||
checked={isEnabled}
|
||||
onChange={toggleLogging}
|
||||
disabled={isLoading || Boolean(error)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
|
||||
import { useAppContext } from '../../../app_context';
|
||||
import { LoadingErrorBanner } from '../../error_banner';
|
||||
import { LoadingState, UpgradeAssistantTabProps } from '../../types';
|
||||
import { UpgradeAssistantTabProps } from '../../types';
|
||||
import { Steps } from './steps';
|
||||
|
||||
export const OverviewTab: FunctionComponent<UpgradeAssistantTabProps> = (props) => {
|
||||
|
@ -56,9 +56,7 @@ export const OverviewTab: FunctionComponent<UpgradeAssistantTabProps> = (props)
|
|||
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>
|
||||
{props.loadingState === LoadingState.Success && <Steps {...props} />}
|
||||
|
||||
{props.loadingState === LoadingState.Loading && (
|
||||
{props.isLoading && (
|
||||
<EuiFlexGroup justifyContent="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLoadingSpinner />
|
||||
|
@ -66,9 +64,9 @@ export const OverviewTab: FunctionComponent<UpgradeAssistantTabProps> = (props)
|
|||
</EuiFlexGroup>
|
||||
)}
|
||||
|
||||
{props.loadingState === LoadingState.Error && (
|
||||
<LoadingErrorBanner loadingError={props.loadingError} />
|
||||
)}
|
||||
{props.checkupData && <Steps {...props} />}
|
||||
|
||||
{props.loadingError && <LoadingErrorBanner loadingError={props.loadingError} />}
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</>
|
||||
|
|
|
@ -33,6 +33,7 @@ const WAIT_FOR_RELEASE_STEP = (majorVersion: number, nextMajorVersion: number) =
|
|||
nextEsVersion: `${nextMajorVersion}.0`,
|
||||
},
|
||||
}),
|
||||
'data-test-subj': 'waitForReleaseStep',
|
||||
children: (
|
||||
<>
|
||||
<EuiText grow={false}>
|
||||
|
@ -58,6 +59,7 @@ const START_UPGRADE_STEP = (isCloudEnabled: boolean, esDocBasePath: string) => (
|
|||
title: i18n.translate('xpack.upgradeAssistant.overviewTab.steps.startUpgradeStep.stepTitle', {
|
||||
defaultMessage: 'Start your upgrade',
|
||||
}),
|
||||
'data-test-subj': 'startUpgradeStep',
|
||||
children: (
|
||||
<Fragment>
|
||||
<EuiText grow={false}>
|
||||
|
@ -100,7 +102,7 @@ export const Steps: FunctionComponent<UpgradeAssistantTabProps> = ({
|
|||
}, {} as { [checkupType: string]: number });
|
||||
|
||||
// Uncomment when START_UPGRADE_STEP is in use!
|
||||
const { kibanaVersionInfo, docLinks, http /* , isCloudEnabled */ } = useAppContext();
|
||||
const { kibanaVersionInfo, docLinks /* , isCloudEnabled */ } = useAppContext();
|
||||
|
||||
const { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } = docLinks;
|
||||
const esDocBasePath = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`;
|
||||
|
@ -127,6 +129,7 @@ export const Steps: FunctionComponent<UpgradeAssistantTabProps> = ({
|
|||
}
|
||||
),
|
||||
status: countByType.cluster ? 'warning' : 'complete',
|
||||
'data-test-subj': 'clusterIssuesStep',
|
||||
children: (
|
||||
<EuiText>
|
||||
{countByType.cluster ? (
|
||||
|
@ -185,6 +188,7 @@ export const Steps: FunctionComponent<UpgradeAssistantTabProps> = ({
|
|||
}
|
||||
),
|
||||
status: countByType.indices ? 'warning' : 'complete',
|
||||
'data-test-subj': 'indicesIssuesStep',
|
||||
children: (
|
||||
<EuiText>
|
||||
{countByType.indices ? (
|
||||
|
@ -235,6 +239,7 @@ export const Steps: FunctionComponent<UpgradeAssistantTabProps> = ({
|
|||
defaultMessage: 'Review the Elasticsearch deprecation logs',
|
||||
}
|
||||
),
|
||||
'data-test-subj': 'deprecationLoggingStep',
|
||||
children: (
|
||||
<Fragment>
|
||||
<EuiText grow={false}>
|
||||
|
@ -273,7 +278,7 @@ export const Steps: FunctionComponent<UpgradeAssistantTabProps> = ({
|
|||
)}
|
||||
describedByIds={['deprecation-logging']}
|
||||
>
|
||||
<DeprecationLoggingToggle http={http} />
|
||||
<DeprecationLoggingToggle />
|
||||
</EuiFormRow>
|
||||
</Fragment>
|
||||
),
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
import React from 'react';
|
||||
|
||||
import { EnrichedDeprecationInfo, UpgradeAssistantStatus } from '../../../common/types';
|
||||
import { ResponseError } from '../lib/api';
|
||||
|
||||
export interface UpgradeAssistantTabProps {
|
||||
alertBanner?: React.ReactNode;
|
||||
checkupData?: UpgradeAssistantStatus;
|
||||
checkupData?: UpgradeAssistantStatus | null;
|
||||
deprecations?: EnrichedDeprecationInfo[];
|
||||
refreshCheckupData: () => Promise<void>;
|
||||
loadingError?: Error;
|
||||
loadingState: LoadingState;
|
||||
refreshCheckupData: () => void;
|
||||
loadingError: ResponseError | null;
|
||||
isLoading: boolean;
|
||||
setSelectedTabIndex: (tabIndex: number) => void;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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 { HttpSetup } from 'src/core/public';
|
||||
import { UpgradeAssistantStatus } from '../../../common/types';
|
||||
import { API_BASE_PATH } from '../../../common/constants';
|
||||
import {
|
||||
UseRequestConfig,
|
||||
SendRequestConfig,
|
||||
SendRequestResponse,
|
||||
sendRequest as _sendRequest,
|
||||
useRequest as _useRequest,
|
||||
} from '../../shared_imports';
|
||||
|
||||
export interface ResponseError {
|
||||
statusCode: number;
|
||||
message: string | Error;
|
||||
attributes?: Record<string, any>;
|
||||
}
|
||||
|
||||
export class ApiService {
|
||||
private client: HttpSetup | undefined;
|
||||
|
||||
private useRequest<R = any, E = ResponseError>(config: UseRequestConfig) {
|
||||
if (!this.client) {
|
||||
throw new Error('API service has not be initialized.');
|
||||
}
|
||||
return _useRequest<R, E>(this.client, config);
|
||||
}
|
||||
|
||||
private sendRequest<D = any, E = ResponseError>(
|
||||
config: SendRequestConfig
|
||||
): Promise<SendRequestResponse<D, E>> {
|
||||
if (!this.client) {
|
||||
throw new Error('API service has not be initialized.');
|
||||
}
|
||||
return _sendRequest<D, E>(this.client, config);
|
||||
}
|
||||
|
||||
public setup(httpClient: HttpSetup): void {
|
||||
this.client = httpClient;
|
||||
}
|
||||
|
||||
public useLoadUpgradeStatus() {
|
||||
return this.useRequest<UpgradeAssistantStatus>({
|
||||
path: `${API_BASE_PATH}/status`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
public async sendTelemetryData(telemetryData: { [tabName: string]: boolean }) {
|
||||
const result = await this.sendRequest({
|
||||
path: `${API_BASE_PATH}/stats/ui_open`,
|
||||
method: 'put',
|
||||
body: JSON.stringify(telemetryData),
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async getDeprecationLogging() {
|
||||
const result = await this.sendRequest<{ isEnabled: boolean }>({
|
||||
path: `${API_BASE_PATH}/deprecation_logging`,
|
||||
method: 'get',
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public async updateDeprecationLogging(loggingData: { isEnabled: boolean }) {
|
||||
const result = await this.sendRequest({
|
||||
path: `${API_BASE_PATH}/deprecation_logging`,
|
||||
method: 'put',
|
||||
body: JSON.stringify(loggingData),
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async updateIndexSettings(indexName: string, settings: string[]) {
|
||||
const result = await this.sendRequest({
|
||||
path: `${API_BASE_PATH}/${indexName}/index_settings`,
|
||||
method: 'post',
|
||||
body: {
|
||||
settings: JSON.stringify(settings),
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const apiService = new ApiService();
|
|
@ -10,6 +10,7 @@ import { ManagementAppMountParams } from '../../../../../src/plugins/management/
|
|||
import { UA_READONLY_MODE } from '../../common/constants';
|
||||
import { renderApp } from './render_app';
|
||||
import { KibanaVersionContext } from './app_context';
|
||||
import { apiService } from './lib/api';
|
||||
|
||||
export async function mountManagementSection(
|
||||
coreSetup: CoreSetup,
|
||||
|
@ -18,14 +19,19 @@ export async function mountManagementSection(
|
|||
kibanaVersionInfo: KibanaVersionContext
|
||||
) {
|
||||
const [{ i18n, docLinks, notifications }] = await coreSetup.getStartServices();
|
||||
const { http } = coreSetup;
|
||||
|
||||
apiService.setup(http);
|
||||
|
||||
return renderApp({
|
||||
element: params.element,
|
||||
isCloudEnabled,
|
||||
http: coreSetup.http,
|
||||
http,
|
||||
i18n,
|
||||
docLinks,
|
||||
kibanaVersionInfo,
|
||||
notifications,
|
||||
isReadOnlyMode: UA_READONLY_MODE,
|
||||
api: apiService,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { AppDependencies, RootComponent } from './app';
|
||||
import { ApiService } from './lib/api';
|
||||
|
||||
interface BootDependencies extends AppDependencies {
|
||||
element: HTMLElement;
|
||||
api: ApiService;
|
||||
}
|
||||
|
||||
export const renderApp = (deps: BootDependencies) => {
|
||||
|
|
14
x-pack/plugins/upgrade_assistant/public/shared_imports.ts
Normal file
14
x-pack/plugins/upgrade_assistant/public/shared_imports.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
sendRequest,
|
||||
SendRequestConfig,
|
||||
SendRequestResponse,
|
||||
useRequest,
|
||||
UseRequestConfig,
|
||||
} from '../../../../src/plugins/es_ui_shared/public/';
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { API_BASE_PATH } from '../../common/constants';
|
||||
import { getUpgradeAssistantStatus } from '../lib/es_migration_apis';
|
||||
import { versionCheckHandlerWrapper } from '../lib/es_version_precheck';
|
||||
import { RouteDependencies } from '../types';
|
||||
|
@ -16,7 +17,7 @@ export function registerClusterCheckupRoutes({ cloud, router, licensing, log }:
|
|||
|
||||
router.get(
|
||||
{
|
||||
path: '/api/upgrade_assistant/status',
|
||||
path: `${API_BASE_PATH}/status`,
|
||||
validate: false,
|
||||
},
|
||||
versionCheckHandlerWrapper(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { API_BASE_PATH } from '../../common/constants';
|
||||
|
||||
import {
|
||||
getDeprecationLoggingStatus,
|
||||
|
@ -17,7 +18,7 @@ import { RouteDependencies } from '../types';
|
|||
export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) {
|
||||
router.get(
|
||||
{
|
||||
path: '/api/upgrade_assistant/deprecation_logging',
|
||||
path: `${API_BASE_PATH}/deprecation_logging`,
|
||||
validate: false,
|
||||
},
|
||||
versionCheckHandlerWrapper(
|
||||
|
@ -38,7 +39,7 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies)
|
|||
|
||||
router.put(
|
||||
{
|
||||
path: '/api/upgrade_assistant/deprecation_logging',
|
||||
path: `${API_BASE_PATH}/deprecation_logging`,
|
||||
validate: {
|
||||
body: schema.object({
|
||||
isEnabled: schema.boolean(),
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { API_BASE_PATH } from '../../../common/constants';
|
||||
import {
|
||||
ElasticsearchServiceStart,
|
||||
kibanaResponseFactory,
|
||||
|
@ -85,7 +86,7 @@ export function registerReindexIndicesRoutes(
|
|||
{ credentialStore, router, licensing, log }: RouteDependencies,
|
||||
getWorker: () => ReindexWorker
|
||||
) {
|
||||
const BASE_PATH = '/api/upgrade_assistant/reindex';
|
||||
const BASE_PATH = `${API_BASE_PATH}/reindex`;
|
||||
|
||||
// Start reindex for an index
|
||||
router.post(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { API_BASE_PATH } from '../../common/constants';
|
||||
import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis';
|
||||
import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis';
|
||||
import { RouteDependencies } from '../types';
|
||||
|
@ -13,7 +14,7 @@ import { RouteDependencies } from '../types';
|
|||
export function registerTelemetryRoutes({ router, getSavedObjectsService }: RouteDependencies) {
|
||||
router.put(
|
||||
{
|
||||
path: '/api/upgrade_assistant/stats/ui_open',
|
||||
path: `${API_BASE_PATH}/stats/ui_open`,
|
||||
validate: {
|
||||
body: schema.object({
|
||||
overview: schema.boolean({ defaultValue: false }),
|
||||
|
@ -37,7 +38,7 @@ export function registerTelemetryRoutes({ router, getSavedObjectsService }: Rout
|
|||
|
||||
router.put(
|
||||
{
|
||||
path: '/api/upgrade_assistant/stats/ui_reindex',
|
||||
path: `${API_BASE_PATH}/stats/ui_reindex`,
|
||||
validate: {
|
||||
body: schema.object({
|
||||
close: schema.boolean({ defaultValue: false }),
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { API_BASE_PATH } from '../../common/constants';
|
||||
import { versionCheckHandlerWrapper } from '../lib/es_version_precheck';
|
||||
import { RouteDependencies } from '../types';
|
||||
|
||||
export function registerUpdateSettingsRoute({ router }: RouteDependencies) {
|
||||
router.post(
|
||||
{
|
||||
path: '/api/upgrade_assistant/{indexName}/index_settings',
|
||||
path: `${API_BASE_PATH}/{indexName}/index_settings`,
|
||||
validate: {
|
||||
params: schema.object({
|
||||
indexName: schema.string(),
|
||||
|
|
|
@ -6,18 +6,45 @@
|
|||
*/
|
||||
|
||||
import sinon, { SinonFakeServer } from 'sinon';
|
||||
import { API_BASE_PATH } from '../../common/constants';
|
||||
import { UpgradeAssistantStatus } from '../../common/types';
|
||||
import { ResponseError } from '../../public/application/lib/api';
|
||||
|
||||
// Register helpers to mock HTTP Requests
|
||||
const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
|
||||
const setLoadStatusResponse = (
|
||||
response?: UpgradeAssistantStatus,
|
||||
error?: { body?: Error; status: number }
|
||||
) => {
|
||||
const status = error ? error.status || 400 : 200;
|
||||
const body = error ? error.body : response;
|
||||
const setLoadStatusResponse = (response?: UpgradeAssistantStatus, error?: ResponseError) => {
|
||||
const status = error ? error.statusCode || 400 : 200;
|
||||
const body = error ? error : response;
|
||||
|
||||
server.respondWith('GET', '/api/upgrade_assistant/status', [
|
||||
server.respondWith('GET', `${API_BASE_PATH}/status`, [
|
||||
status,
|
||||
{ 'Content-Type': 'application/json' },
|
||||
JSON.stringify(body),
|
||||
]);
|
||||
};
|
||||
|
||||
const setLoadDeprecationLoggingResponse = (
|
||||
response?: { isEnabled: boolean },
|
||||
error?: ResponseError
|
||||
) => {
|
||||
const status = error ? error.statusCode || 400 : 200;
|
||||
const body = error ? error : response;
|
||||
|
||||
server.respondWith('GET', `${API_BASE_PATH}/deprecation_logging`, [
|
||||
status,
|
||||
{ 'Content-Type': 'application/json' },
|
||||
JSON.stringify(body),
|
||||
]);
|
||||
};
|
||||
|
||||
const setUpdateDeprecationLoggingResponse = (
|
||||
response?: { isEnabled: boolean },
|
||||
error?: ResponseError
|
||||
) => {
|
||||
const status = error ? error.statusCode || 400 : 200;
|
||||
const body = error ? error : response;
|
||||
|
||||
server.respondWith('PUT', `${API_BASE_PATH}/deprecation_logging`, [
|
||||
status,
|
||||
{ 'Content-Type': 'application/json' },
|
||||
JSON.stringify(body),
|
||||
|
@ -25,7 +52,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
|
|||
};
|
||||
|
||||
const setUpdateIndexSettingsResponse = (response?: object) => {
|
||||
server.respondWith('POST', `/api/upgrade_assistant/:indexName/index_settings`, [
|
||||
server.respondWith('POST', `${API_BASE_PATH}/:indexName/index_settings`, [
|
||||
200,
|
||||
{ 'Content-Type': 'application/json' },
|
||||
JSON.stringify(response),
|
||||
|
@ -34,6 +61,8 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
|
|||
|
||||
return {
|
||||
setLoadStatusResponse,
|
||||
setLoadDeprecationLoggingResponse,
|
||||
setUpdateDeprecationLoggingResponse,
|
||||
setUpdateIndexSettingsResponse,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -59,4 +59,7 @@ export type IndicesTestSubjects =
|
|||
| 'expandAll'
|
||||
| 'removeIndexSettingsButton'
|
||||
| 'deprecationsContainer'
|
||||
| 'permissionsError'
|
||||
| 'upgradeStatusError'
|
||||
| 'noDeprecationsPrompt'
|
||||
| string;
|
||||
|
|
|
@ -22,4 +22,11 @@ export const setup = async (overrides?: any): Promise<OverviewTestBed> => {
|
|||
return testBed;
|
||||
};
|
||||
|
||||
export type OverviewTestSubjects = 'comingSoonPrompt' | 'upgradeAssistantPageContent';
|
||||
export type OverviewTestSubjects =
|
||||
| 'comingSoonPrompt'
|
||||
| 'upgradeAssistantPageContent'
|
||||
| 'upgradedPrompt'
|
||||
| 'partiallyUpgradedPrompt'
|
||||
| 'upgradeAssistantDeprecationToggle'
|
||||
| 'deprecationLoggingStep'
|
||||
| 'upgradeStatusError';
|
||||
|
|
|
@ -16,26 +16,30 @@ import { HttpSetup } from '../../../../../src/core/public';
|
|||
import { mockKibanaSemverVersion, UA_READONLY_MODE } from '../../common/constants';
|
||||
import { AppContextProvider } from '../../public/application/app_context';
|
||||
import { init as initHttpRequests } from './http_requests';
|
||||
import { apiService } from '../../public/application/lib/api';
|
||||
|
||||
const mockHttpClient = axios.create({ adapter: axiosXhrAdapter });
|
||||
|
||||
const contextValue = {
|
||||
http: (mockHttpClient as unknown) as HttpSetup,
|
||||
isCloudEnabled: false,
|
||||
docLinks: docLinksServiceMock.createStartContract(),
|
||||
kibanaVersionInfo: {
|
||||
currentMajor: mockKibanaSemverVersion.major,
|
||||
prevMajor: mockKibanaSemverVersion.major - 1,
|
||||
nextMajor: mockKibanaSemverVersion.major + 1,
|
||||
},
|
||||
isReadOnlyMode: UA_READONLY_MODE,
|
||||
notifications: notificationServiceMock.createStartContract(),
|
||||
};
|
||||
|
||||
export const WithAppDependencies = (
|
||||
Comp: React.FunctionComponent<Record<string, unknown>>,
|
||||
overrides: Record<string, unknown> = {}
|
||||
) => (props: Record<string, unknown>) => {
|
||||
apiService.setup((mockHttpClient as unknown) as HttpSetup);
|
||||
|
||||
const contextValue = {
|
||||
http: (mockHttpClient as unknown) as HttpSetup,
|
||||
isCloudEnabled: false,
|
||||
docLinks: docLinksServiceMock.createStartContract(),
|
||||
kibanaVersionInfo: {
|
||||
currentMajor: mockKibanaSemverVersion.major,
|
||||
prevMajor: mockKibanaSemverVersion.major - 1,
|
||||
nextMajor: mockKibanaSemverVersion.major + 1,
|
||||
},
|
||||
isReadOnlyMode: UA_READONLY_MODE,
|
||||
notifications: notificationServiceMock.createStartContract(),
|
||||
api: apiService,
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContextProvider value={{ ...contextValue, ...overrides }}>
|
||||
<Comp {...props} />
|
||||
|
|
|
@ -15,79 +15,179 @@ describe('Indices tab', () => {
|
|||
let testBed: IndicesTestBed;
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
|
||||
const upgradeStatusMockResponse = {
|
||||
readyForUpgrade: false,
|
||||
cluster: [],
|
||||
indices: [
|
||||
{
|
||||
level: 'warning' as MIGRATION_DEPRECATION_LEVEL,
|
||||
message: indexSettingDeprecations.translog.deprecationMessage,
|
||||
url: 'doc_url',
|
||||
index: 'my_index',
|
||||
deprecatedIndexSettings: indexSettingDeprecations.translog.settings,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(upgradeStatusMockResponse);
|
||||
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
testBed = await setupIndicesPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
// Navigate to the indices tab
|
||||
testBed.actions.clickTab('indices');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
server.restore();
|
||||
});
|
||||
|
||||
describe('Fix indices button', () => {
|
||||
test('removes deprecated index settings', async () => {
|
||||
const { component, actions, exists, find } = testBed;
|
||||
describe('with deprecations', () => {
|
||||
const upgradeStatusMockResponse = {
|
||||
readyForUpgrade: false,
|
||||
cluster: [],
|
||||
indices: [
|
||||
{
|
||||
level: 'warning' as MIGRATION_DEPRECATION_LEVEL,
|
||||
message: indexSettingDeprecations.translog.deprecationMessage,
|
||||
url: 'doc_url',
|
||||
index: 'my_index',
|
||||
deprecatedIndexSettings: indexSettingDeprecations.translog.settings,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(exists('deprecationsContainer')).toBe(true);
|
||||
|
||||
// Open all deprecations
|
||||
actions.clickExpandAll();
|
||||
|
||||
const accordionTestSubj = `depgroup_${indexSettingDeprecations.translog.deprecationMessage
|
||||
.split(' ')
|
||||
.join('_')}`;
|
||||
beforeEach(async () => {
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(upgradeStatusMockResponse);
|
||||
httpRequestsMockHelpers.setLoadDeprecationLoggingResponse({ isEnabled: true });
|
||||
|
||||
await act(async () => {
|
||||
find(`${accordionTestSubj}.removeIndexSettingsButton`).simulate('click');
|
||||
testBed = await setupIndicesPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const modal = document.body.querySelector(
|
||||
'[data-test-subj="indexSettingsDeleteConfirmModal"]'
|
||||
);
|
||||
const confirmButton: HTMLButtonElement | null = modal!.querySelector(
|
||||
'[data-test-subj="confirmModalConfirmButton"]'
|
||||
);
|
||||
|
||||
expect(modal).not.toBe(null);
|
||||
expect(modal!.textContent).toContain('Remove deprecated settings');
|
||||
|
||||
const indexName = upgradeStatusMockResponse.indices[0].index;
|
||||
|
||||
httpRequestsMockHelpers.setUpdateIndexSettingsResponse({
|
||||
acknowledged: true,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
confirmButton!.click();
|
||||
});
|
||||
const { actions, component } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
const request = server.requests[server.requests.length - 1];
|
||||
// Navigate to the indices tab
|
||||
await act(async () => {
|
||||
actions.clickTab('indices');
|
||||
});
|
||||
|
||||
expect(request.method).toBe('POST');
|
||||
expect(request.url).toBe(`/api/upgrade_assistant/${indexName}/index_settings`);
|
||||
expect(request.status).toEqual(200);
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('renders deprecations', () => {
|
||||
const { exists, find } = testBed;
|
||||
expect(exists('deprecationsContainer')).toBe(true);
|
||||
expect(find('indexCount').text()).toEqual('1');
|
||||
});
|
||||
|
||||
describe('fix indices button', () => {
|
||||
test('removes deprecated index settings', async () => {
|
||||
const { component, actions, exists, find } = testBed;
|
||||
|
||||
expect(exists('deprecationsContainer')).toBe(true);
|
||||
|
||||
// Open all deprecations
|
||||
actions.clickExpandAll();
|
||||
|
||||
const accordionTestSubj = `depgroup_${indexSettingDeprecations.translog.deprecationMessage
|
||||
.split(' ')
|
||||
.join('_')}`;
|
||||
|
||||
await act(async () => {
|
||||
find(`${accordionTestSubj}.removeIndexSettingsButton`).simulate('click');
|
||||
});
|
||||
|
||||
// We need to read the document "body" as the modal is added there and not inside
|
||||
// the component DOM tree.
|
||||
const modal = document.body.querySelector(
|
||||
'[data-test-subj="indexSettingsDeleteConfirmModal"]'
|
||||
);
|
||||
const confirmButton: HTMLButtonElement | null = modal!.querySelector(
|
||||
'[data-test-subj="confirmModalConfirmButton"]'
|
||||
);
|
||||
|
||||
expect(modal).not.toBe(null);
|
||||
expect(modal!.textContent).toContain('Remove deprecated settings');
|
||||
|
||||
const indexName = upgradeStatusMockResponse.indices[0].index;
|
||||
|
||||
httpRequestsMockHelpers.setUpdateIndexSettingsResponse({
|
||||
acknowledged: true,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
confirmButton!.click();
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
const request = server.requests[server.requests.length - 1];
|
||||
|
||||
expect(request.method).toBe('POST');
|
||||
expect(request.url).toBe(`/api/upgrade_assistant/${indexName}/index_settings`);
|
||||
expect(request.status).toEqual(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('no deprecations', () => {
|
||||
beforeEach(async () => {
|
||||
const noDeprecationsResponse = {
|
||||
readyForUpgrade: false,
|
||||
cluster: [],
|
||||
indices: [],
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(noDeprecationsResponse);
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setupIndicesPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const { actions, component } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
// Navigate to the indices tab
|
||||
await act(async () => {
|
||||
actions.clickTab('indices');
|
||||
});
|
||||
|
||||
component.update();
|
||||
});
|
||||
|
||||
test('renders prompt', () => {
|
||||
const { exists, find } = testBed;
|
||||
expect(exists('noDeprecationsPrompt')).toBe(true);
|
||||
expect(find('noDeprecationsPrompt').text()).toContain('All clear!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
test('handles 403', async () => {
|
||||
const error = {
|
||||
statusCode: 403,
|
||||
error: 'Forbidden',
|
||||
message: 'Forbidden',
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(undefined, error);
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setupIndicesPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const { component, exists, find } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
expect(exists('permissionsError')).toBe(true);
|
||||
expect(find('permissionsError').text()).toContain(
|
||||
'You do not have sufficient privileges to view this page.'
|
||||
);
|
||||
});
|
||||
|
||||
test('handles generic error', async () => {
|
||||
const error = {
|
||||
statusCode: 500,
|
||||
error: 'Internal server error',
|
||||
message: 'Internal server error',
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(undefined, error);
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setupIndicesPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const { component, exists, find } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
expect(exists('upgradeStatusError')).toBe(true);
|
||||
expect(find('upgradeStatusError').text()).toContain(
|
||||
'An error occurred while retrieving the checkup results.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { OverviewTestBed, setupOverviewPage } from './helpers';
|
||||
import { OverviewTestBed, setupOverviewPage, setupEnvironment } from './helpers';
|
||||
|
||||
describe('Overview page', () => {
|
||||
let testBed: OverviewTestBed;
|
||||
|
@ -27,20 +27,160 @@ describe('Overview page', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Tabs', () => {
|
||||
describe('Overview content', () => {
|
||||
const { server, httpRequestsMockHelpers } = setupEnvironment();
|
||||
|
||||
const upgradeStatusMockResponse = {
|
||||
readyForUpgrade: false,
|
||||
cluster: [],
|
||||
indices: [],
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(upgradeStatusMockResponse);
|
||||
httpRequestsMockHelpers.setLoadDeprecationLoggingResponse({ isEnabled: true });
|
||||
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
// Override the default context value to verify tab content renders as expected
|
||||
// This will be the default behavior on the last minor before the next major release (e.g., v7.15)
|
||||
testBed = await setupOverviewPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
testBed.component.update();
|
||||
});
|
||||
|
||||
test('renders the Upgrade Assistant overview tab', () => {
|
||||
afterAll(() => {
|
||||
server.restore();
|
||||
});
|
||||
|
||||
test('renders the overview tab', () => {
|
||||
const { exists } = testBed;
|
||||
|
||||
expect(exists('comingSoonPrompt')).toBe(false);
|
||||
expect(exists('upgradeAssistantPageContent')).toBe(true);
|
||||
});
|
||||
|
||||
describe('Deprecation logging', () => {
|
||||
test('toggles deprecation logging', async () => {
|
||||
const { form, find, component } = testBed;
|
||||
|
||||
httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse({ isEnabled: false });
|
||||
|
||||
expect(find('upgradeAssistantDeprecationToggle').props()['aria-checked']).toBe(true);
|
||||
expect(find('upgradeAssistantDeprecationToggle').props().disabled).toBe(false);
|
||||
expect(find('deprecationLoggingStep').find('.euiSwitch__label').text()).toContain('On');
|
||||
|
||||
await act(async () => {
|
||||
form.toggleEuiSwitch('upgradeAssistantDeprecationToggle');
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
expect(find('upgradeAssistantDeprecationToggle').props()['aria-checked']).toBe(false);
|
||||
expect(find('upgradeAssistantDeprecationToggle').props().disabled).toBe(false);
|
||||
expect(find('deprecationLoggingStep').find('.euiSwitch__label').text()).toContain('Off');
|
||||
});
|
||||
|
||||
test('handles network error', async () => {
|
||||
const error = {
|
||||
statusCode: 500,
|
||||
error: 'Internal server error',
|
||||
message: 'Internal server error',
|
||||
};
|
||||
|
||||
const { form, find, component } = testBed;
|
||||
|
||||
httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(undefined, error);
|
||||
|
||||
expect(find('upgradeAssistantDeprecationToggle').props()['aria-checked']).toBe(true);
|
||||
expect(find('upgradeAssistantDeprecationToggle').props().disabled).toBe(false);
|
||||
expect(find('deprecationLoggingStep').find('.euiSwitch__label').text()).toContain('On');
|
||||
|
||||
await act(async () => {
|
||||
form.toggleEuiSwitch('upgradeAssistantDeprecationToggle');
|
||||
});
|
||||
|
||||
component.update();
|
||||
|
||||
expect(find('upgradeAssistantDeprecationToggle').props()['aria-checked']).toBe(true);
|
||||
expect(find('upgradeAssistantDeprecationToggle').props().disabled).toBe(true);
|
||||
expect(find('deprecationLoggingStep').find('.euiSwitch__label').text()).toContain(
|
||||
'Could not load logging state'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error handling', () => {
|
||||
test('handles network failure', async () => {
|
||||
const error = {
|
||||
statusCode: 500,
|
||||
error: 'Internal server error',
|
||||
message: 'Internal server error',
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(undefined, error);
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setupOverviewPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const { component, exists, find } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
expect(exists('upgradeStatusError')).toBe(true);
|
||||
expect(find('upgradeStatusError').text()).toContain(
|
||||
'An error occurred while retrieving the checkup results.'
|
||||
);
|
||||
});
|
||||
|
||||
test('handles partially upgraded error', async () => {
|
||||
const error = {
|
||||
statusCode: 426,
|
||||
error: 'Upgrade required',
|
||||
message: 'There are some nodes running a different version of Elasticsearch',
|
||||
attributes: {
|
||||
allNodesUpgraded: false,
|
||||
},
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(undefined, error);
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setupOverviewPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const { component, exists, find } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
expect(exists('partiallyUpgradedPrompt')).toBe(true);
|
||||
expect(find('partiallyUpgradedPrompt').text()).toContain('Your cluster is upgrading');
|
||||
});
|
||||
|
||||
test('handles upgrade error', async () => {
|
||||
const error = {
|
||||
statusCode: 426,
|
||||
error: 'Upgrade required',
|
||||
message: 'There are some nodes running a different version of Elasticsearch',
|
||||
attributes: {
|
||||
allNodesUpgraded: true,
|
||||
},
|
||||
};
|
||||
|
||||
httpRequestsMockHelpers.setLoadStatusResponse(undefined, error);
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setupOverviewPage({ isReadOnlyMode: false });
|
||||
});
|
||||
|
||||
const { component, exists, find } = testBed;
|
||||
|
||||
component.update();
|
||||
|
||||
expect(exists('upgradedPrompt')).toBe(true);
|
||||
expect(find('upgradedPrompt').text()).toContain('Your cluster has been upgraded');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue