Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove conditions before restart a workspace #1188

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2018-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import { getStartWorkspaceConditions } from '@/components/WorkspaceProgress/utils';
import { DevWorkspaceBuilder } from '@/store/__mocks__/devWorkspaceBuilder';

describe('WorkspaceProgress utils', () => {
beforeEach(() => {});

afterEach(() => {
jest.clearAllMocks();
});

describe('getStartWorkspaceCondition', () => {
it('should return an empty array as a default value', () => {
const devWorkspace = new DevWorkspaceBuilder().build();

expect(devWorkspace.status?.conditions).toBeUndefined();

const conditions = getStartWorkspaceConditions(devWorkspace);

expect(conditions).toEqual([]);
});
it('should return conditions from the devWorkspace', () => {
const status = {
conditions: [
{
type: 'Stopped',
status: 'False',
reason: 'LimitReached',
message: 'Workspace stopped due to error.',
},
],
};
const devWorkspace = new DevWorkspaceBuilder().withStatus(status).build();

const conditions = getStartWorkspaceConditions(devWorkspace);

expect(conditions).toEqual(status.conditions);
});
});
it('should filter conditions that are not related to the workspace start', () => {
const status = {
conditions: [
{
message: 'DevWorkspace is starting',
status: 'True',
type: 'Started',
},
{
message: 'Resolved plugins and parents from DevWorkspace',
status: 'True',
type: 'DevWorkspaceResolved',
},
{
message: 'Storage ready',
status: 'True',
type: 'StorageReady',
},
{
message: 'Networking ready',
status: 'True',
type: 'RoutingReady',
},
{
message: 'DevWorkspace serviceaccount ready',
status: 'True',
type: 'ServiceAccountReady',
},
{
message: 'Waiting for workspace deployment',
status: 'False',
type: 'DeploymentReady',
},
],
};
const devWorkspace = new DevWorkspaceBuilder().withStatus(status).build();

const conditions = getStartWorkspaceConditions(devWorkspace);

expect(conditions).not.toEqual(status.conditions);
expect(conditions).toEqual([
{
message: 'DevWorkspace is starting',
status: 'True',
type: 'Started',
},
{
message: 'Resolved plugins and parents from DevWorkspace',
status: 'True',
type: 'DevWorkspaceResolved',
},
{
message: 'Storage ready',
status: 'True',
type: 'StorageReady',
},
{
message: 'Networking ready',
status: 'True',
type: 'RoutingReady',
},
{
message: 'DevWorkspace serviceaccount ready',
status: 'True',
type: 'ServiceAccountReady',
},
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ import StartingStepInitialize from '@/components/WorkspaceProgress/StartingSteps
import StartingStepOpenWorkspace from '@/components/WorkspaceProgress/StartingSteps/OpenWorkspace';
import StartingStepStartWorkspace from '@/components/WorkspaceProgress/StartingSteps/StartWorkspace';
import StartingStepWorkspaceConditions from '@/components/WorkspaceProgress/StartingSteps/WorkspaceConditions';
import { ConditionType, isWorkspaceStatusCondition } from '@/components/WorkspaceProgress/utils';
import {
ConditionType,
getStartWorkspaceConditions,
isWorkspaceStatusCondition,
} from '@/components/WorkspaceProgress/utils';
import WorkspaceProgressWizard, {
WorkspaceProgressWizardStep,
} from '@/components/WorkspaceProgress/Wizard';
Expand Down Expand Up @@ -184,7 +188,7 @@ class Progress extends React.Component<Props, State> {
workspace.status === DevWorkspaceStatus.FAILING ||
workspace.status === DevWorkspaceStatus.FAILED)
) {
const conditions = workspace.ref.status?.conditions || [];
const conditions = getStartWorkspaceConditions(workspace.ref);

const lastScore = this.scoreConditions(this.state.conditions);
const score = this.scoreConditions(conditions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

import { V1alpha2DevWorkspaceStatusConditions } from '@devfile/api';

import devfileApi from '@/services/devfileApi';

export type ConditionType = V1alpha2DevWorkspaceStatusConditions & {
status: 'True' | 'False' | 'Unknown';
};
Expand All @@ -37,6 +39,24 @@ export function isConditionReady(
);
}

export function getStartWorkspaceConditions(
workspace: devfileApi.DevWorkspace,
): V1alpha2DevWorkspaceStatusConditions[] {
if (!workspace.status?.conditions || workspace.status.conditions.length === 0) {
return [];
}
const conditions = [...workspace.status.conditions];
// remove all conditions that are not related to the workspace start
for (let i = conditions.length; i > 0; i--) {
if (conditions[i - 1].type === 'ServiceAccountReady') {
conditions.length = i;
break;
}
}

return conditions;
}

export function isConditionError(
condition: ConditionType,
prevCondition: ConditionType | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,75 @@ describe('DevWorkspace store, actions', () => {
expect(actions).toStrictEqual(expectedActions);
});

it('should remove all workspace conditions in the store before start a DevWorkspace', async () => {
(checkRunningWorkspacesLimit as jest.Mock).mockImplementation(() => undefined);
(isRunningDevWorkspacesClusterLimitExceeded as jest.Mock).mockReturnValue(
Promise.resolve(true),
);

// set a condition with an error message to the devWorkspace
devWorkspace.status = {
devworkspaceId: '1234',
conditions: [
{
type: 'Stopped',
status: 'False',
reason: 'LimitReached',
message: 'Workspace stopped due to error.',
},
],
};

const store = storeBuilder.withDevWorkspaces({ workspaces: [devWorkspace] }).build();

await store.dispatch(testStore.actionCreators.startWorkspace(devWorkspace));

const actions = store.getActions();

const expectedDevWorkspaceWithEmptyConditions = Object.assign({}, devWorkspace, {
status: {
devworkspaceId: '1234',
conditions: [],
},
});

const expectedActions: Array<
| testStore.KnownAction
| testDevWorkspaceClusterStore.KnownAction
| ServerConfigStore.KnownAction
> = [
{
type: testStore.Type.UPDATE_DEVWORKSPACE,
workspace: expectedDevWorkspaceWithEmptyConditions,
},
{
type: testDevWorkspaceClusterStore.Type.REQUEST_DEVWORKSPACES_CLUSTER,
check: AUTHORIZED,
},
{
type: testDevWorkspaceClusterStore.Type.RECEIVED_DEVWORKSPACES_CLUSTER,
isRunningDevWorkspacesClusterLimitExceeded: true,
},
{
type: testStore.Type.REQUEST_DEVWORKSPACE,
check: AUTHORIZED,
},
{
type: 'REQUEST_DW_SERVER_CONFIG',
},
{
config: {} as api.IServerConfig,
type: 'RECEIVE_DW_SERVER_CONFIG',
},
{
type: testStore.Type.UPDATE_DEVWORKSPACE,
workspace: devWorkspace,
},
];

expect(actions).toStrictEqual(expectedActions);
});

it('should create REQUEST_DEVWORKSPACE and RECEIVE_DEVWORKSPACE_ERROR when failed to start a DevWorkspace', async () => {
(checkRunningWorkspacesLimit as jest.Mock).mockImplementation(() => {
throw new Error('Limit reached.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,13 @@ export const actionCreators: ActionCreators = {
console.warn(`Workspace ${_workspace.metadata.name} already started`);
return;
}
if (workspace.status?.conditions && workspace.status?.conditions?.length > 0) {
workspace.status.conditions = [];
dispatch({
type: Type.UPDATE_DEVWORKSPACE,
workspace,
});
}
try {
await OAuthService.refreshTokenIfProjectExists(workspace);
} catch (e: unknown) {
Expand Down Expand Up @@ -421,8 +428,6 @@ export const actionCreators: ActionCreators = {
const startingTimeout = 10000;
await Promise.race([defer.promise, delay(startingTimeout)]);
toDispose.dispose();

getDevWorkspaceClient().checkForDevWorkspaceError(startingWorkspace);
} catch (e) {
// Skip unauthorised errors. The page is redirecting to an SCM authentication page.
if (common.helpers.errors.includesAxiosResponse(e) && isOAuthResponse(e.response.data)) {
Expand Down
Loading