Skip to content

Commit

Permalink
Add endpoint dedicated to surfacing the cluster upgrade state, and a …
Browse files Browse the repository at this point in the history
…client-side poll.
  • Loading branch information
cjcenizal committed Oct 9, 2021
1 parent c6a9326 commit db265e1
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 4 deletions.
18 changes: 15 additions & 3 deletions x-pack/plugins/upgrade_assistant/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useEffect, useState } from 'react';
import React, { useState, useEffect } from 'react';
import { Router, Switch, Route, Redirect } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiEmptyPrompt, EuiPageContent } from '@elastic/eui';
Expand All @@ -21,7 +21,7 @@ import { EsDeprecations, ComingSoonPrompt, KibanaDeprecations, Overview } from '

const { GlobalFlyoutProvider } = GlobalFlyout;

const App: React.FunctionComponent = () => {
const AppWithoutPolling: React.FunctionComponent = () => {
const {
isReadOnlyMode,
services: { api },
Expand All @@ -34,7 +34,7 @@ const App: React.FunctionComponent = () => {
api.onClusterUpgradeStateChange((newClusterUpgradeState: ClusterUpgradeState) => {
setClusterUpradeState(newClusterUpgradeState);
});
}, [api, setClusterUpradeState]);
}, [api]);

// Read-only mode will be enabled up until the last minor before the next major release
if (isReadOnlyMode) {
Expand Down Expand Up @@ -118,6 +118,18 @@ const App: React.FunctionComponent = () => {
);
};

export const App: React.FunctionComponent = () => {
const {
services: { api },
} = useAppContext();

// This is a hack to avoid the app getting stuck in an infinite render loop,
// as noted in api.ts.
api.useLoadClusterUpgradeStatus();

return <AppWithoutPolling />;
};

export const AppWithRouter = ({ history }: { history: ScopedHistory }) => {
return (
<Router history={history}>
Expand Down
17 changes: 16 additions & 1 deletion x-pack/plugins/upgrade_assistant/public/application/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '../../../common/types';
import {
API_BASE_PATH,
CLUSTER_UPGRADE_STATUS_POLL_INTERVAL_MS,
DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS,
CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS,
} from '../../../common/constants';
Expand Down Expand Up @@ -48,6 +49,12 @@ export class ApiService {
throw new Error('API service has not been initialized.');
}
const response = _useRequest<R, ResponseError>(this.client, config);
// NOTE: This will cause an infinite render loop in any component that both
// consumes the hook calling this useRequest function and also handles
// cluster upgrade errors. This is because we're calling handleClusterUpgradeError
// every time useRequest is called, which will be on every render. If handling
// the cluster upgrade error causes a state change in the consuming component,
// that will trigger a render, which will call useRequest again, and so on.
this.handleClusterUpgradeError<UseRequestResponse<R, ResponseError>>(response.error);
return response;
}
Expand All @@ -67,10 +74,18 @@ export class ApiService {
this.client = httpClient;
}

public onClusterUpgradeStateChange(listener: ClusterUpgradeStateListener): void {
public onClusterUpgradeStateChange(listener: ClusterUpgradeStateListener) {
this.clusterUpgradeStateListeners.push(listener);
}

public useLoadClusterUpgradeStatus() {
return this.useRequest({
path: `${API_BASE_PATH}/cluster_upgrade_status`,
method: 'get',
pollIntervalMs: CLUSTER_UPGRADE_STATUS_POLL_INTERVAL_MS,
});
}

public useLoadCloudBackupStatus() {
return this.useRequest<CloudBackupStatus>({
path: `${API_BASE_PATH}/cloud_backup_status`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { API_BASE_PATH } from '../../common/constants';
import { versionCheckHandlerWrapper } from '../lib/es_version_precheck';
import { RouteDependencies } from '../types';

export function registerClusterUpgradeStatusRoutes({ router }: RouteDependencies) {
router.get(
{ path: `${API_BASE_PATH}/cluster_upgrade_status`, validate: false },
// We're just depending on the version check to return a 426.
// Otherwise we just return a 200.
versionCheckHandlerWrapper(async (context, request, response) => {
return response.ok();
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RouteDependencies } from '../types';

import { registerAppRoutes } from './app';
import { registerCloudBackupStatusRoutes } from './cloud_backup_status';
import { registerClusterUpgradeStatusRoutes } from './cluster_upgrade_status';
import { registerESDeprecationRoutes } from './es_deprecations';
import { registerDeprecationLoggingRoutes } from './deprecation_logging';
import { registerReindexIndicesRoutes, registerBatchReindexIndicesRoutes } from './reindex_indices';
Expand All @@ -21,6 +22,7 @@ import { registerUpgradeStatusRoute } from './status';
export function registerRoutes(dependencies: RouteDependencies, getWorker: () => ReindexWorker) {
registerAppRoutes(dependencies);
registerCloudBackupStatusRoutes(dependencies);
registerClusterUpgradeStatusRoutes(dependencies);
registerESDeprecationRoutes(dependencies);
registerDeprecationLoggingRoutes(dependencies);
registerReindexIndicesRoutes(dependencies, getWorker);
Expand Down

0 comments on commit db265e1

Please sign in to comment.