From 03e4f76bb2289c8bb55cbe2b7cb4f116f392fc90 Mon Sep 17 00:00:00 2001 From: YanJin Date: Mon, 14 Dec 2020 09:29:43 +0100 Subject: [PATCH] ui/ducks/volumes: Change the payload of createVolume to an array Refs: #2964 --- ui/src/ducks/app/volumes.js | 132 +++++++++++++++---------------- ui/src/ducks/app/volumes.test.js | 109 +++++++++++++------------ 2 files changed, 124 insertions(+), 117 deletions(-) diff --git a/ui/src/ducks/app/volumes.js b/ui/src/ducks/app/volumes.js index 21b2c8dd83..e4e2189454 100644 --- a/ui/src/ducks/app/volumes.js +++ b/ui/src/ducks/app/volumes.js @@ -118,8 +118,8 @@ export const updateStorageClassAction = (payload) => { return { type: UPDATE_STORAGECLASS, payload }; }; -export const createVolumeAction = (newVolume) => { - return { type: CREATE_VOLUMES, payload: { newVolume } }; +export const createVolumeAction = (newVolumes) => { + return { type: CREATE_VOLUMES, payload: { newVolumes } }; }; export const refreshVolumesAction = () => { @@ -205,7 +205,7 @@ export function* fetchStorageClass() { * This function construct the body that is needed to create a volume. * Then it calls K8s API to create it. * - * @param {object} newVolume - fields of the createVolume form + * @param {array} newVolume - The array of fields of the createVolume form * @param {string} nodeName * * More examples in volumes.test.js @@ -213,89 +213,89 @@ export function* fetchStorageClass() { * * const action = { * payload: { - * newVolume: { + * newVolume: [{ * name: 'volume1', * node: 'bootrap', * storageClass: 'metalk8s-default', * type: 'sparseLoopDevice', * size: '1Gi' - * }, + * }], * } * }; * * createVolumes(action) */ export function* createVolumes({ payload }) { - const { newVolume } = payload; - - const body = { - apiVersion: 'storage.metalk8s.scality.com/v1alpha1', - kind: 'Volume', - metadata: { - name: newVolume.name, - labels: newVolume.labels, - }, - spec: { - nodeName: newVolume.node, - storageClassName: newVolume.storageClass, - template: { - metadata: { - labels: newVolume.labels, + const { newVolumes } = payload; + for (var i = 0; i < newVolumes?.length; i++) { + const body = { + apiVersion: 'storage.metalk8s.scality.com/v1alpha1', + kind: 'Volume', + metadata: { + name: newVolumes[i].name, + labels: newVolumes[i].labels, + }, + spec: { + nodeName: newVolumes[i].node, + storageClassName: newVolumes[i].storageClass, + template: { + metadata: { + labels: newVolumes[i].labels, + }, }, }, - }, - }; - - /** - * Size should be set for SPARSE_LOOP_DEVICE - * Path should be set for RAW_BLOCK_DEVICE - */ - let isNewVolumeValid = - newVolume && - newVolume.name && - newVolume.storageClass && - ((newVolume.type === SPARSE_LOOP_DEVICE && newVolume.size) || - (newVolume.type === RAW_BLOCK_DEVICE && newVolume.path)); - - if (isNewVolumeValid) { - if (newVolume.type === SPARSE_LOOP_DEVICE) { - body.spec.sparseLoopDevice = { size: newVolume.size }; - } else { - body.spec.rawBlockDevice = { devicePath: newVolume.path }; - } - - const result = yield call(VolumesApi.createVolume, body); - if (!result.error) { - yield call( - history.push, - `/volumes/${newVolume.name}/overview?node=${newVolume.node}`, - ); - yield put( - addNotificationSuccessAction({ - title: intl.translate('volume_creation'), - message: intl.translate('volume_creation_success', { - name: newVolume.name, + }; + /** + * Size should be set for SPARSE_LOOP_DEVICE + * Path should be set for RAW_BLOCK_DEVICE + */ + let isNewVolumeValid = + newVolumes[i] && + newVolumes[i].name && + newVolumes[i].storageClass && + ((newVolumes[i].type === SPARSE_LOOP_DEVICE && newVolumes[i].size) || + (newVolumes[i].type === RAW_BLOCK_DEVICE && newVolumes[i].path)); + + if (isNewVolumeValid) { + if (newVolumes[i].type === SPARSE_LOOP_DEVICE) { + body.spec.sparseLoopDevice = { size: newVolumes[i].size }; + } else { + body.spec.rawBlockDevice = { devicePath: newVolumes[i].path }; + } + + const result = yield call(VolumesApi.createVolume, body); + if (!result.error) { + yield call( + history.push, + `/volumes/${newVolumes[i].name}/overview?node=${newVolumes[i].node}`, + ); + yield put( + addNotificationSuccessAction({ + title: intl.translate('volume_creation'), + message: intl.translate('volume_creation_success', { + name: newVolumes[i].name, + }), }), - }), - ); + ); + } else { + yield put( + addNotificationErrorAction({ + title: intl.translate('volume_creation'), + message: intl.translate('volume_creation_failed', { + name: newVolumes[i].name, + }), + }), + ); + } } else { + // We might want to change this behavior later yield put( addNotificationErrorAction({ - title: intl.translate('volume_creation'), - message: intl.translate('volume_creation_failed', { - name: newVolume.name, - }), + title: 'Volume Form Error', + message: 'Volume not created, some fields are missing.', }), ); } - } else { - // We might want to change this behavior later - yield put( - addNotificationErrorAction({ - title: 'Volume Form Error', - message: 'Volume not created, some fields are missing.', - }), - ); } } diff --git a/ui/src/ducks/app/volumes.test.js b/ui/src/ducks/app/volumes.test.js index cb3e8b8611..698797a37c 100644 --- a/ui/src/ducks/app/volumes.test.js +++ b/ui/src/ducks/app/volumes.test.js @@ -281,20 +281,22 @@ it('does not update PV if there is an error', () => { it('create volume with the type sparseloopdevice', () => { const action = { payload: { - newVolume: { - name: 'volume1', - node: 'bootstrap', - storageClass: 'metalk8s-default', - type: 'sparseLoopDevice', - size: '1Gi', - labels: { - name: 'carlito', + newVolumes: [ + { + name: 'volume1', + node: 'bootstrap', + storageClass: 'metalk8s-default', + type: 'sparseLoopDevice', + size: '1Gi', + labels: { + name: 'carlito', + }, }, - }, + ], }, }; - const { newVolume } = action.payload; + const { newVolumes } = action.payload; const gen = createVolumes(action); @@ -302,16 +304,15 @@ it('create volume with the type sparseloopdevice', () => { apiVersion: 'storage.metalk8s.scality.com/v1alpha1', kind: 'Volume', metadata: { - name: newVolume.name, + name: newVolumes[0].name, labels: { name: 'carlito', }, }, spec: { - nodeName: newVolume.node, - storageClassName: newVolume.storageClass, - sparseLoopDevice: { size: newVolume.size }, - storageClassName: 'metalk8s-default', + nodeName: newVolumes[0].node, + storageClassName: newVolumes[0].storageClass, + sparseLoopDevice: { size: newVolumes[0].size }, template: { metadata: { labels: { @@ -349,7 +350,7 @@ it('create volume with the type sparseloopdevice', () => { expect(gen.next(result).value).toEqual( call( history.push, - `/volumes/${newVolume.name}/overview?node=${newVolume.node}`, + `/volumes/${newVolumes[0].name}/overview?node=${newVolumes[0].node}`, ), ); @@ -363,34 +364,36 @@ it('create volume with the type sparseloopdevice', () => { it('create a volume with the type rawBlockdevice', () => { const action = { payload: { - newVolume: { - name: 'volume1', - node: 'bootstrap', - storageClass: 'metalk8s-default', - type: 'rawBlockDevice', - path: '/dev/disk1', - labels: { - name: 'carlito', + newVolumes: [ + { + name: 'volume1', + node: 'bootstrap', + storageClass: 'metalk8s-default', + type: 'rawBlockDevice', + path: '/dev/disk1', + labels: { + name: 'carlito', + }, }, - }, + ], }, }; - const { newVolume } = action.payload; + const { newVolumes } = action.payload; const gen = createVolumes(action); const body = { apiVersion: 'storage.metalk8s.scality.com/v1alpha1', kind: 'Volume', metadata: { - name: newVolume.name, + name: newVolumes[0].name, labels: { name: 'carlito', }, }, spec: { - nodeName: newVolume.node, - storageClassName: newVolume.storageClass, - rawBlockDevice: { devicePath: newVolume.path }, + nodeName: newVolumes[0].node, + storageClassName: newVolumes[0].storageClass, + rawBlockDevice: { devicePath: newVolumes[0].path }, template: { metadata: { labels: { @@ -426,7 +429,7 @@ it('create a volume with the type rawBlockdevice', () => { expect(gen.next(result).value).toEqual( call( history.push, - `/volumes/${newVolume.name}/overview?node=${newVolume.node}`, + `/volumes/${newVolumes[0].name}/overview?node=${newVolumes[0].node}`, ), ); expect(gen.next().value.payload.action.type).toEqual( @@ -439,12 +442,14 @@ it('create a volume with the type rawBlockdevice', () => { it('display a notification when the params are wrong', () => { const action = { payload: { - newVolume: { - name: 'volume1', - storageClass: 'metalk8s-default', - type: 'rawBlockDevice', - path: '', - }, + newVolumes: [ + { + name: 'volume1', + storageClass: 'metalk8s-default', + type: 'rawBlockDevice', + path: '', + }, + ], nodeName: 'bootstrap', }, }; @@ -458,33 +463,35 @@ it('display a notification when the params are wrong', () => { it('does not create a volume when there is an error', () => { const action = { payload: { - newVolume: { - name: 'volume1', - node: 'bootstrap', - storageClass: 'metalk8s-default', - type: 'rawBlockDevice', - path: '/dev/disk1', - labels: { - name: 'carlito', + newVolumes: [ + { + name: 'volume1', + node: 'bootstrap', + storageClass: 'metalk8s-default', + type: 'rawBlockDevice', + path: '/dev/disk1', + labels: { + name: 'carlito', + }, }, - }, + ], }, }; - const { newVolume } = action.payload; + const { newVolumes } = action.payload; const gen = createVolumes(action); const body = { apiVersion: 'storage.metalk8s.scality.com/v1alpha1', kind: 'Volume', metadata: { - name: newVolume.name, + name: newVolumes[0].name, labels: { name: 'carlito', }, }, spec: { - nodeName: newVolume.node, - storageClassName: newVolume.storageClass, - rawBlockDevice: { devicePath: newVolume.path }, + nodeName: newVolumes[0].node, + storageClassName: newVolumes[0].storageClass, + rawBlockDevice: { devicePath: newVolumes[0].path }, template: { metadata: { labels: {