Skip to content

Commit 352e9bd

Browse files
committed
feat(pci-block-storage): delete snapshots before retyping
ref: #TAPC-4569 Signed-off-by: Adrien Turmo <[email protected]>
1 parent 31aff7d commit 352e9bd

File tree

8 files changed

+646
-348
lines changed

8 files changed

+646
-348
lines changed

packages/manager/apps/pci-block-storage/public/translations/retype/Messages_fr_FR.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
"pci_projects_project_storages_blocks_retype_change_type_title": "Sélectionner le type",
55
"pci_projects_project_storages_blocks_retype_change_encryption_title": "Sélectionner le chiffrement",
66
"pci_projects_project_storages_blocks_retype_encryption_not_available": "Le chiffrement n'est pas disponible dans cette région",
7+
"pci_projects_project_storages_blocks_retype_confirm_action_label": "Entrer \"{{ confirmWord }}\" pour confirmer votre choix.",
8+
"pci_projects_project_storages_blocks_retype_confirm_action_confirm_button": "Confirmer et continuer",
79
"pci_projects_project_storages_blocks_retype_detach_volume": "Pour modifier votre type d'offre, vous devez détacher le volume de son instance {{ instance }}",
8-
"pci_projects_project_storages_blocks_retype_detach_volume_label": "Entrer \"{{ confirmWord }}\" pour confirmer votre choix.",
9-
"pci_projects_project_storages_blocks_retype_detach_volume_confirm_button": "Confirmer et continuer",
10-
"pci_projects_project_storages_blocks_retype_detach_volume_error": "Une erreur s'est produite lors du détachement de l'instance. Nous vous invitons à vous rendre sur <0>la page block storage</0> afin de détacher l'instance manuellement"
10+
"pci_projects_project_storages_blocks_retype_detach_volume_error": "Une erreur s'est produite lors du détachement de l'instance. Nous vous invitons à vous rendre sur <0>la page block storage</0> afin de détacher l'instance manuellement.",
11+
"pci_projects_project_storages_blocks_retype_delete_snapshots": "Pour modifier votre type d’offre vous devez avant supprimer les snapshots rattachés à votre volume.",
12+
"pci_projects_project_storages_blocks_retype_delete_snapshots_error": "Une erreur s'est produite lors de la suppression des snapshots. Nous vous invitons à vous rendre sur <0>la page des snapshots</0> afin de les supprimer manuellement."
1113
}

packages/manager/apps/pci-block-storage/src/pages/retype/Retype.page.spec.tsx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import {
88
useCatalogWithPreselection,
99
} from '@/api/hooks/useCatalogWithPreselection';
1010
import { useAttachedInstances } from '@/api/hooks/useInstance';
11+
import { useVolumeSnapshots } from '@/api/hooks/useSnapshot';
1112
import { TAttachedInstance } from '@/api/select/instances';
13+
import { TVolumeSnapshot } from '@/api/data/snapshot';
1214

1315
const PROJECT_ID = '123';
1416
const VOLUME_ID = '1';
@@ -21,6 +23,10 @@ vi.mock('@/api/hooks/useInstance', () => ({
2123
useAttachedInstances: vi.fn(),
2224
}));
2325

26+
vi.mock('@/api/hooks/useSnapshot', () => ({
27+
useVolumeSnapshots: vi.fn(),
28+
}));
29+
2430
vi.mock('./Retype.component', () => ({
2531
Retype: () => <div>Retype instance</div>,
2632
}));
@@ -29,6 +35,10 @@ vi.mock('./RetypeDetachInstance.component', () => ({
2935
RetypeDetachInstance: () => <div>Detach instance</div>,
3036
}));
3137

38+
vi.mock('./RetypeDeleteSnapshots.component', () => ({
39+
RetypeDeleteSnapshots: () => <div>Delete snapshots</div>,
40+
}));
41+
3242
vi.mocked(useParams).mockReturnValue({
3343
projectId: PROJECT_ID,
3444
volumeId: VOLUME_ID,
@@ -46,6 +56,11 @@ const instance = {
4656
name: 'instance',
4757
} as TAttachedInstance;
4858

59+
const snapshot = {
60+
id: '333',
61+
volumeId: VOLUME_ID,
62+
} as TVolumeSnapshot;
63+
4964
describe('RetypePage', () => {
5065
it('should render spinner while fetching volumeRetypeModel', () => {
5166
vi.mocked(useCatalogWithPreselection).mockReturnValue({
@@ -57,6 +72,11 @@ describe('RetypePage', () => {
5772
isPending: false,
5873
} as ReturnType<typeof useAttachedInstances>);
5974

75+
vi.mocked(useVolumeSnapshots).mockReturnValue({
76+
data: [],
77+
isPending: false,
78+
} as ReturnType<typeof useVolumeSnapshots>);
79+
6080
const { getByTestId, queryByText } = render(<RetypePage />);
6181

6282
expect(getByTestId('retypePage-loader')).toBeVisible();
@@ -67,6 +87,7 @@ describe('RetypePage', () => {
6787
).toBeNull();
6888
expect(queryByText('Detach instance')).toBeNull();
6989
expect(queryByText('Retype instance')).toBeNull();
90+
expect(queryByText('Delete snapshots')).toBeNull();
7091
});
7192

7293
it('should render spinner while fetching instances', () => {
@@ -79,6 +100,39 @@ describe('RetypePage', () => {
79100
isPending: true,
80101
} as ReturnType<typeof useAttachedInstances>);
81102

103+
vi.mocked(useVolumeSnapshots).mockReturnValue({
104+
data: [],
105+
isPending: false,
106+
} as ReturnType<typeof useVolumeSnapshots>);
107+
108+
const { getByTestId, queryByText } = render(<RetypePage />);
109+
110+
expect(getByTestId('retypePage-loader')).toBeVisible();
111+
expect(
112+
queryByText(
113+
'retype:pci_projects_project_storages_blocks_retype_cant_retype',
114+
),
115+
).toBeNull();
116+
expect(queryByText('Detach instance')).toBeNull();
117+
expect(queryByText('Retype instance')).toBeNull();
118+
expect(queryByText('Delete snapshots')).toBeNull();
119+
});
120+
121+
it('should render spinner while fetching snapshots', () => {
122+
vi.mocked(useCatalogWithPreselection).mockReturnValue({
123+
data: [],
124+
isPending: false,
125+
} as ReturnType<typeof useCatalogWithPreselection>);
126+
127+
vi.mocked(useAttachedInstances).mockReturnValue({
128+
isPending: false,
129+
} as ReturnType<typeof useAttachedInstances>);
130+
131+
vi.mocked(useVolumeSnapshots).mockReturnValue({
132+
data: [],
133+
isPending: true,
134+
} as ReturnType<typeof useVolumeSnapshots>);
135+
82136
const { getByTestId, queryByText } = render(<RetypePage />);
83137

84138
expect(getByTestId('retypePage-loader')).toBeVisible();
@@ -89,6 +143,7 @@ describe('RetypePage', () => {
89143
).toBeNull();
90144
expect(queryByText('Detach instance')).toBeNull();
91145
expect(queryByText('Retype instance')).toBeNull();
146+
expect(queryByText('Delete snapshots')).toBeNull();
92147
});
93148

94149
it('should render warning message if volumeRetypeModel data is an empty array', () => {
@@ -102,6 +157,11 @@ describe('RetypePage', () => {
102157
isPending: false,
103158
} as ReturnType<typeof useAttachedInstances>);
104159

160+
vi.mocked(useVolumeSnapshots).mockReturnValue({
161+
data: [],
162+
isPending: false,
163+
} as ReturnType<typeof useVolumeSnapshots>);
164+
105165
const { getByText, queryByText, queryByTestId } = render(<RetypePage />);
106166

107167
expect(
@@ -112,6 +172,7 @@ describe('RetypePage', () => {
112172
expect(queryByTestId('retypePage-loader')).toBeNull();
113173
expect(queryByText('Detach instance')).toBeNull();
114174
expect(queryByText('Retype instance')).toBeNull();
175+
expect(queryByText('Delete snapshots')).toBeNull();
115176
});
116177

117178
it('should render RetypeDetachInstance if there is an instance', () => {
@@ -125,6 +186,68 @@ describe('RetypePage', () => {
125186
isPending: false,
126187
} as ReturnType<typeof useAttachedInstances>);
127188

189+
vi.mocked(useVolumeSnapshots).mockReturnValue({
190+
data: [],
191+
isPending: false,
192+
} as ReturnType<typeof useVolumeSnapshots>);
193+
194+
const { getByText, queryByText, queryByTestId } = render(<RetypePage />);
195+
196+
expect(getByText('Detach instance')).toBeVisible();
197+
expect(
198+
queryByText(
199+
'retype:pci_projects_project_storages_blocks_retype_cant_retype',
200+
),
201+
).toBeNull();
202+
expect(queryByTestId('retypePage-loader')).toBeNull();
203+
expect(queryByText('Retype instance')).toBeNull();
204+
expect(queryByText('Delete snapshots')).toBeNull();
205+
});
206+
207+
it('should render RetypeDeleteSnapshots if there is at least one snapshot', () => {
208+
vi.mocked(useCatalogWithPreselection).mockReturnValue({
209+
data: [volumeRetypeModel],
210+
isPending: false,
211+
} as ReturnType<typeof useCatalogWithPreselection>);
212+
213+
vi.mocked(useAttachedInstances).mockReturnValue({
214+
data: [],
215+
isPending: false,
216+
} as ReturnType<typeof useAttachedInstances>);
217+
218+
vi.mocked(useVolumeSnapshots).mockReturnValue({
219+
data: [snapshot],
220+
isPending: false,
221+
} as ReturnType<typeof useVolumeSnapshots>);
222+
223+
const { getByText, queryByText, queryByTestId } = render(<RetypePage />);
224+
225+
expect(getByText('Delete snapshots')).toBeVisible();
226+
expect(
227+
queryByText(
228+
'retype:pci_projects_project_storages_blocks_retype_cant_retype',
229+
),
230+
).toBeNull();
231+
expect(queryByTestId('retypePage-loader')).toBeNull();
232+
expect(queryByText('Retype instance')).toBeNull();
233+
});
234+
235+
it('should render RetypeDetachInstance if there is an instance and a snapshot', () => {
236+
vi.mocked(useCatalogWithPreselection).mockReturnValue({
237+
data: [volumeRetypeModel],
238+
isPending: false,
239+
} as ReturnType<typeof useCatalogWithPreselection>);
240+
241+
vi.mocked(useAttachedInstances).mockReturnValue({
242+
data: [instance],
243+
isPending: false,
244+
} as ReturnType<typeof useAttachedInstances>);
245+
246+
vi.mocked(useVolumeSnapshots).mockReturnValue({
247+
data: [snapshot],
248+
isPending: false,
249+
} as ReturnType<typeof useVolumeSnapshots>);
250+
128251
const { getByText, queryByText, queryByTestId } = render(<RetypePage />);
129252

130253
expect(getByText('Detach instance')).toBeVisible();
@@ -135,6 +258,7 @@ describe('RetypePage', () => {
135258
).toBeNull();
136259
expect(queryByTestId('retypePage-loader')).toBeNull();
137260
expect(queryByText('Retype instance')).toBeNull();
261+
expect(queryByText('Delete snapshots')).toBeNull();
138262
});
139263

140264
it('should render Retype if there is no instance and a volumeRetypeModel', () => {
@@ -148,6 +272,11 @@ describe('RetypePage', () => {
148272
isPending: false,
149273
} as ReturnType<typeof useAttachedInstances>);
150274

275+
vi.mocked(useVolumeSnapshots).mockReturnValue({
276+
data: [],
277+
isPending: false,
278+
} as ReturnType<typeof useVolumeSnapshots>);
279+
151280
const { getByText, queryByText, queryByTestId } = render(<RetypePage />);
152281

153282
expect(getByText('Retype instance')).toBeVisible();
@@ -158,5 +287,6 @@ describe('RetypePage', () => {
158287
).toBeNull();
159288
expect(queryByTestId('retypePage-loader')).toBeNull();
160289
expect(queryByText('Detach instance')).toBeNull();
290+
expect(queryByText('Delete snapshots')).toBeNull();
161291
});
162292
});

packages/manager/apps/pci-block-storage/src/pages/retype/Retype.page.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import { useTranslation } from 'react-i18next';
1313
import { useMemo } from 'react';
1414
import { useCatalogWithPreselection } from '@/api/hooks/useCatalogWithPreselection';
1515
import { useAttachedInstances } from '@/api/hooks/useInstance';
16+
import { useVolumeSnapshots } from '@/api/hooks/useSnapshot';
1617
import { Retype } from './Retype.component';
1718
import { RetypeDetachInstance } from './RetypeDetachInstance.component';
19+
import { RetypeDeleteSnapshots } from './RetypeDeleteSnapshots.component';
1820

1921
const RetypePage = () => {
2022
const { t } = useTranslation(['retype']);
@@ -31,7 +33,13 @@ const RetypePage = () => {
3133
isPending: isInstancesPending,
3234
} = useAttachedInstances(projectId, volumeId);
3335

34-
const isPending = isCatalogPending || isInstancesPending;
36+
const { data: snapshots, isPending: isSnapshotsPending } = useVolumeSnapshots(
37+
projectId,
38+
volumeId,
39+
);
40+
41+
const isPending =
42+
isCatalogPending || isInstancesPending || isSnapshotsPending;
3543

3644
const displayedForm = useMemo(() => {
3745
if (isPending) {
@@ -65,6 +73,16 @@ const RetypePage = () => {
6573
);
6674
}
6775

76+
if (snapshots?.length > 0) {
77+
return (
78+
<RetypeDeleteSnapshots
79+
snapshots={snapshots}
80+
projectId={projectId}
81+
volumeId={volumeId}
82+
/>
83+
);
84+
}
85+
6886
return (
6987
<Retype
7088
volumeModelData={volumeModelData}

0 commit comments

Comments
 (0)