Skip to content

Commit

Permalink
Instance deregistration sagas (#1746)
Browse files Browse the repository at this point in the history
* Create required deregistration reducer functions

* Implement instance deregistration sagas

* Improve test descritpion texts

* Rename some reducer functions to use unset prefix
  • Loading branch information
arbulu89 committed Aug 29, 2023
1 parent aa70415 commit 7343c8a
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 13 deletions.
27 changes: 26 additions & 1 deletion assets/js/state/databases.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createSlice } from '@reduxjs/toolkit';
import { createAction, createSlice } from '@reduxjs/toolkit';
import { instancesMatch, upsertInstances, updateInstance } from './instances';

const initialState = {
Expand Down Expand Up @@ -89,6 +89,24 @@ export const databasesListSlice = createSlice({
}
);
},
setDatabaseInstanceDeregistering: (state, { payload: instance }) => {
state.databaseInstances = updateInstance(
state.databaseInstances,
instance,
{
deregistering: true,
}
);
},
unsetDatabaseInstanceDeregistering: (state, { payload: instance }) => {
state.databaseInstances = updateInstance(
state.databaseInstances,
instance,
{
deregistering: false,
}
);
},
},
});

Expand All @@ -102,6 +120,11 @@ export const DATABASE_INSTANCE_HEALTH_CHANGED =
'DATABASE_INSTANCE_HEALTH_CHANGED';
export const DATABASE_INSTANCE_SYSTEM_REPLICATION_CHANGED =
'DATABASE_INSTANCE_SYSTEM_REPLICATION_CHANGED';
export const DEREGISTER_DATABASE_INSTANCE = 'DEREGISTER_DATABASE_INSTANCE';

export const deregisterDatabaseInstance = createAction(
DEREGISTER_DATABASE_INSTANCE
);

export const {
startDatabasesLoading,
Expand All @@ -116,6 +139,8 @@ export const {
updateDatabaseInstanceSystemReplication,
addTagToDatabase,
removeTagFromDatabase,
setDatabaseInstanceDeregistering,
unsetDatabaseInstanceDeregistering,
} = databasesListSlice.actions;

export default databasesListSlice.reducer;
44 changes: 44 additions & 0 deletions assets/js/state/databases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import databaseReducer, {
upsertDatabaseInstances,
updateDatabaseInstanceHealth,
updateDatabaseInstanceSystemReplication,
setDatabaseInstanceDeregistering,
unsetDatabaseInstanceDeregistering,
} from '@state/databases';
import {
databaseFactory,
Expand Down Expand Up @@ -126,4 +128,46 @@ describe('Databases reducer', () => {

expect(databaseReducer(initialState, action)).toEqual(expectedState);
});

it('should set database instance in deregistering state', () => {
const instance = databaseInstanceFactory.build();

const initialState = {
databaseInstances: [instance],
};

const action = setDatabaseInstanceDeregistering(instance);

const expectedState = {
databaseInstances: [
{
...instance,
deregistering: true,
},
],
};

expect(databaseReducer(initialState, action)).toEqual(expectedState);
});

it('should remove deregistering state from database instance', () => {
const instance = databaseInstanceFactory.build();

const initialState = {
databaseInstances: [instance],
};

const action = unsetDatabaseInstanceDeregistering(instance);

const expectedState = {
databaseInstances: [
{
...instance,
deregistering: false,
},
],
};

expect(databaseReducer(initialState, action)).toEqual(expectedState);
});
});
4 changes: 2 additions & 2 deletions assets/js/state/hosts.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const hostsListSlice = createSlice({
return host;
});
},
setHostNotDeregistering: (state, action) => {
unsetHostDeregistering: (state, action) => {
state.hosts = state.hosts.map((host) => {
if (host.id === action.payload.id) {
return { ...host, deregistering: false };
Expand Down Expand Up @@ -142,7 +142,7 @@ export const {
setHostListDeregisterable,
setHostNotDeregisterable,
setHostDeregistering,
setHostNotDeregistering,
unsetHostDeregistering,
startHostsLoading,
stopHostsLoading,
removeHost,
Expand Down
4 changes: 2 additions & 2 deletions assets/js/state/hosts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import hostsReducer, {
setHostListDeregisterable,
setHostNotDeregisterable,
setHostDeregistering,
setHostNotDeregistering,
unsetHostDeregistering,
updateSelectedChecks,
} from '@state/hosts';
import { hostFactory } from '@lib/test-utils/factories';
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('Hosts reducer', () => {
hosts: [host1, host2],
};

const action = setHostNotDeregistering(host1);
const action = unsetHostDeregistering(host1);

const expectedState = {
hosts: [{ ...host1, deregistering: false }, host2],
Expand Down
34 changes: 33 additions & 1 deletion assets/js/state/sagas/databases.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { put, select, takeEvery } from 'redux-saga/effects';
import { call, put, select, takeEvery } from 'redux-saga/effects';
import { del } from '@lib/network';

import {
DATABASE_REGISTERED,
DATABASE_DEREGISTERED,
Expand All @@ -8,20 +10,25 @@ import {
DATABASE_INSTANCE_DEREGISTERED,
DATABASE_INSTANCE_HEALTH_CHANGED,
DATABASE_INSTANCE_SYSTEM_REPLICATION_CHANGED,
DEREGISTER_DATABASE_INSTANCE,
appendDatabase,
upsertDatabaseInstances,
updateDatabaseHealth,
updateDatabaseInstanceHealth,
updateDatabaseInstanceSystemReplication,
removeDatabase,
removeDatabaseInstance,
setDatabaseInstanceDeregistering,
unsetDatabaseInstanceDeregistering,
} from '@state/databases';

import {
upsertDatabaseInstancesToSapSystem,
removeDatabaseInstanceFromSapSystem,
updateSAPSystemDatabaseInstanceHealth,
updateSAPSystemDatabaseInstanceSystemReplication,
setDatabaseInstanceDeregisteringToSAPSystem,
unsetDatabaseInstanceDeregisteringToSAPSystem,
} from '@state/sapSystems';

import { getDatabase } from '@state/selectors/sapSystem';
Expand Down Expand Up @@ -104,6 +111,30 @@ function* databaseInstanceSystemReplicationChanged({ payload }) {
yield put(updateSAPSystemDatabaseInstanceSystemReplication(payload));
}

export function* deregisterDatabaseInstance({
payload,
payload: { sid, sap_system_id, host_id, instance_number },
}) {
yield put(setDatabaseInstanceDeregistering(payload));
yield put(setDatabaseInstanceDeregisteringToSAPSystem(payload));
try {
yield call(
del,
`/databases/${sap_system_id}/hosts/${host_id}/instances/${instance_number}`
);
} catch (error) {
yield put(
notify({
text: `Error deregistering instance ${instance_number} from ${sid}.`,
icon: '❌',
})
);
} finally {
yield put(unsetDatabaseInstanceDeregistering(payload));
yield put(unsetDatabaseInstanceDeregisteringToSAPSystem(payload));
}
}

export function* watchDatabase() {
yield takeEvery(DATABASE_REGISTERED, databaseRegistered);
yield takeEvery(DATABASE_DEREGISTERED, databaseDeregistered);
Expand All @@ -119,4 +150,5 @@ export function* watchDatabase() {
DATABASE_INSTANCE_SYSTEM_REPLICATION_CHANGED,
databaseInstanceSystemReplicationChanged
);
yield takeEvery(DEREGISTER_DATABASE_INSTANCE, deregisterDatabaseInstance);
}
68 changes: 68 additions & 0 deletions assets/js/state/sagas/databases.test.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
import MockAdapter from 'axios-mock-adapter';

import { recordSaga } from '@lib/test-utils';
import {
databaseDeregistered,
databaseInstanceDeregistered,
databaseRestored,
deregisterDatabaseInstance,
} from '@state/sagas/databases';
import {
upsertDatabaseInstances,
removeDatabase,
removeDatabaseInstance,
appendDatabase,
setDatabaseInstanceDeregistering,
unsetDatabaseInstanceDeregistering,
} from '@state/databases';
import {
removeDatabaseInstanceFromSapSystem,
upsertDatabaseInstancesToSapSystem,
setDatabaseInstanceDeregisteringToSAPSystem,
unsetDatabaseInstanceDeregisteringToSAPSystem,
} from '@state/sapSystems';
import {
databaseFactory,
databaseInstanceFactory,
} from '@lib/test-utils/factories';
import { networkClient } from '@lib/network';
import { notify } from '@state/actions/notifications';

const axiosMock = new MockAdapter(networkClient);

describe('SAP Systems sagas', () => {
beforeEach(() => {
axiosMock.reset();
jest.spyOn(console, 'error').mockImplementation(() => null);
});

afterEach(() => {
/* eslint-disable-next-line */
console.error.mockRestore();
});

it('should remove the database instance', async () => {
const { sap_system_id, host_id, instance_number, sid } =
databaseInstanceFactory.build();
Expand Down Expand Up @@ -82,4 +102,52 @@ describe('SAP Systems sagas', () => {
}),
]);
});

it('should deregister the database instance', async () => {
const instance = databaseInstanceFactory.build();
const { sap_system_id, host_id, instance_number } = instance;

axiosMock
.onDelete(
`/databases/${sap_system_id}/hosts/${host_id}/instances/${instance_number}`
)
.reply(204, {});

const dispatched = await recordSaga(deregisterDatabaseInstance, {
payload: instance,
});

expect(dispatched).toEqual([
setDatabaseInstanceDeregistering(instance),
setDatabaseInstanceDeregisteringToSAPSystem(instance),
unsetDatabaseInstanceDeregistering(instance),
unsetDatabaseInstanceDeregisteringToSAPSystem(instance),
]);
});

it('should notify an error on database instance deregistration request failure', async () => {
const instance = databaseInstanceFactory.build();
const { sid, sap_system_id, host_id, instance_number } = instance;

axiosMock
.onDelete(
`/databases/${sap_system_id}/hosts/${host_id}/instances/${instance_number}`
)
.reply(404, {});

const dispatched = await recordSaga(deregisterDatabaseInstance, {
payload: instance,
});

expect(dispatched).toEqual([
setDatabaseInstanceDeregistering(instance),
setDatabaseInstanceDeregisteringToSAPSystem(instance),
notify({
text: `Error deregistering instance ${instance_number} from ${sid}.`,
icon: '❌',
}),
unsetDatabaseInstanceDeregistering(instance),
unsetDatabaseInstanceDeregisteringToSAPSystem(instance),
]);
});
});
4 changes: 2 additions & 2 deletions assets/js/state/sagas/hosts.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
removeHost,
setHostListDeregisterable,
setHostDeregistering,
setHostNotDeregistering,
unsetHostDeregistering,
appendHost,
} from '@state/hosts';

Expand Down Expand Up @@ -67,7 +67,7 @@ export function* deregisterHost({
})
);
} finally {
yield put(setHostNotDeregistering(payload));
yield put(unsetHostDeregistering(payload));
}
}

Expand Down
6 changes: 3 additions & 3 deletions assets/js/state/sagas/hosts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
setHostListDeregisterable,
removeHost,
setHostDeregistering,
setHostNotDeregistering,
unsetHostDeregistering,
appendHost,
} from '@state/hosts';

Expand Down Expand Up @@ -93,7 +93,7 @@ describe('Hosts sagas', () => {

expect(dispatched).toEqual([
setHostDeregistering(payload),
setHostNotDeregistering(payload),
unsetHostDeregistering(payload),
]);
});

Expand All @@ -111,7 +111,7 @@ describe('Hosts sagas', () => {
text: `Error deregistering host ${hostname}.`,
icon: '❌',
}),
setHostNotDeregistering(payload),
unsetHostDeregistering(payload),
]);
});

Expand Down

0 comments on commit 7343c8a

Please sign in to comment.