diff --git a/x-pack/plugins/upgrade_assistant/public/components/tabs.tsx b/x-pack/plugins/upgrade_assistant/public/components/tabs.tsx
index b99d05ec935690..76cc1e33ca06b2 100644
--- a/x-pack/plugins/upgrade_assistant/public/components/tabs.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/components/tabs.tsx
@@ -26,13 +26,19 @@ import { CheckupTab } from './tabs/checkup';
import { OverviewTab } from './tabs/overview';
import { LoadingState, TelemetryState, UpgradeAssistantTabProps } from './types';
+enum ClusterUpgradeState {
+ needsUpgrade,
+ partiallyUpgraded,
+ upgraded,
+}
+
interface TabsState {
loadingState: LoadingState;
loadingError?: Error;
checkupData?: UpgradeAssistantStatus;
selectedTabIndex: number;
telemetryState: TelemetryState;
- upgradeableCluster: boolean;
+ clusterUpgradeState: ClusterUpgradeState;
}
export class UpgradeAssistantTabsUI extends React.Component<
@@ -44,7 +50,7 @@ export class UpgradeAssistantTabsUI extends React.Component<
this.state = {
loadingState: LoadingState.Loading,
- upgradeableCluster: true,
+ clusterUpgradeState: ClusterUpgradeState.needsUpgrade,
selectedTabIndex: 0,
telemetryState: TelemetryState.Complete,
};
@@ -58,10 +64,10 @@ export class UpgradeAssistantTabsUI extends React.Component<
}
public render() {
- const { selectedTabIndex, telemetryState, upgradeableCluster } = this.state;
+ const { selectedTabIndex, telemetryState, clusterUpgradeState } = this.state;
const tabs = this.tabs;
- if (!upgradeableCluster) {
+ if (clusterUpgradeState === ClusterUpgradeState.partiallyUpgraded) {
return (
@@ -80,7 +86,33 @@ export class UpgradeAssistantTabsUI extends React.Component<
+
+ }
+ />
+
+
+ );
+ } else if (clusterUpgradeState === ClusterUpgradeState.upgraded) {
+ return (
+
+
+
+
+
+ }
+ body={
+
+
}
@@ -134,7 +166,9 @@ export class UpgradeAssistantTabsUI extends React.Component<
if (get(e, 'response.status') === 426) {
this.setState({
loadingState: LoadingState.Success,
- upgradeableCluster: false,
+ clusterUpgradeState: get(e, 'response.data.attributes.allNodesUpgraded', false)
+ ? ClusterUpgradeState.upgraded
+ : ClusterUpgradeState.partiallyUpgraded,
});
} else {
this.setState({ loadingState: LoadingState.Error, loadingError: e });
diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts
index e4735a5e7adf8e..9a0fca6d4139c2 100644
--- a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts
+++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts
@@ -71,11 +71,11 @@ describe('EsVersionPrecheck', () => {
);
});
- it('throws a 426 message when nodes are not on same version', async () => {
+ it('throws a 426 message w/ allNodesUpgraded = false when nodes are not on same version', async () => {
const fakeCallWithRequest = jest.fn().mockResolvedValue({
nodes: {
node1: { version: CURRENT_VERSION.raw },
- node2: { version: CURRENT_VERSION.inc('major').raw },
+ node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw },
},
});
const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest }));
@@ -83,12 +83,31 @@ describe('EsVersionPrecheck', () => {
server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } },
} as any;
- await expect(EsVersionPrecheck.method(fakeRequest, {} as any)).rejects.toHaveProperty(
- 'output.statusCode',
- 426
+ const result = EsVersionPrecheck.method(fakeRequest, {} as any);
+ await expect(result).rejects.toHaveProperty('output.statusCode', 426);
+ await expect(result).rejects.toHaveProperty(
+ 'output.payload.attributes.allNodesUpgraded',
+ false
);
});
+ it('throws a 426 message w/ allNodesUpgraded = true when nodes are on next version', async () => {
+ const fakeCallWithRequest = jest.fn().mockResolvedValue({
+ nodes: {
+ node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw },
+ node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw },
+ },
+ });
+ const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest }));
+ const fakeRequest = {
+ server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } },
+ } as any;
+
+ const result = EsVersionPrecheck.method(fakeRequest, {} as any);
+ await expect(result).rejects.toHaveProperty('output.statusCode', 426);
+ await expect(result).rejects.toHaveProperty('output.payload.attributes.allNodesUpgraded', true);
+ });
+
it('returns true when nodes are on same version', async () => {
const fakeCallWithRequest = jest.fn().mockResolvedValue({
nodes: {
diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts
index 6cb913d6dd582c..d84d5f54444723 100644
--- a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts
+++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts
@@ -31,15 +31,21 @@ export const getAllNodeVersions = async (callCluster: CallCluster) => {
export const verifyAllMatchKibanaVersion = (allNodeVersions: SemVer[]) => {
// Determine if all nodes in the cluster are running the same major version as Kibana.
- const anyDifferentEsNodes = !!allNodeVersions.find(
+ const numDifferentVersion = allNodeVersions.filter(
esNodeVersion => esNodeVersion.major !== CURRENT_VERSION.major
- );
+ ).length;
+ const numSameVersion = allNodeVersions.filter(
+ esNodeVersion => esNodeVersion.major === CURRENT_VERSION.major
+ ).length;
- if (anyDifferentEsNodes) {
- throw new Boom(`There are some nodes running a different version of Elasticsearch`, {
+ if (numDifferentVersion) {
+ const error = new Boom(`There are some nodes running a different version of Elasticsearch`, {
// 426 means "Upgrade Required" and is used when semver compatibility is not met.
statusCode: 426,
});
+
+ error.output.payload.attributes = { allNodesUpgraded: !numSameVersion };
+ throw error;
}
};