From f0e5ec41874905e78a5e2aa65b43baf71bf5ed65 Mon Sep 17 00:00:00 2001 From: Mason Hu Date: Fri, 8 Mar 2024 12:04:24 +0200 Subject: [PATCH] fix: prevent custom config keys being removed when updating resources - Checked edit instances (using getUnhandledKeyValues) - Checked edit profile (using getUnhandledKeyValues) - Checked edit network (using yaml object) - Checked edit network forward (no config keys) - Checked edit storage pool (using PATCH request so it's not a problem) - Checked edit storage volume (updated to use getUnhandledKeyValues) - Checked edit snapshot (no config keys) - Checked edit image (can't edit images so not a problem) - Checked edit project (using getUnhandledKeyValues) Signed-off-by: Mason Hu --- src/pages/storage/forms/StorageVolumeEdit.tsx | 2 +- src/pages/storage/forms/StorageVolumeForm.tsx | 21 ++++++++++++++++++- src/types/storage.d.ts | 4 +++- src/util/formFields.tsx | 8 ++++++- src/util/storageVolume.tsx | 7 ++++++- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/pages/storage/forms/StorageVolumeEdit.tsx b/src/pages/storage/forms/StorageVolumeEdit.tsx index 9309e2089a..21f703a003 100644 --- a/src/pages/storage/forms/StorageVolumeEdit.tsx +++ b/src/pages/storage/forms/StorageVolumeEdit.tsx @@ -41,7 +41,7 @@ const StorageVolumeEdit: FC = ({ volume }) => { initialValues: getStorageVolumeEditValues(volume), validationSchema: StorageVolumeSchema, onSubmit: (values) => { - const saveVolume = volumeFormToPayload(values, project); + const saveVolume = volumeFormToPayload(values, project, volume); updateStorageVolume(values.pool, project, { ...saveVolume, etag: volume.etag, diff --git a/src/pages/storage/forms/StorageVolumeForm.tsx b/src/pages/storage/forms/StorageVolumeForm.tsx index 27ec50b6a2..d31ee15090 100644 --- a/src/pages/storage/forms/StorageVolumeForm.tsx +++ b/src/pages/storage/forms/StorageVolumeForm.tsx @@ -19,6 +19,7 @@ import StorageVolumeFormZFS from "pages/storage/forms/StorageVolumeFormZFS"; import { FormikProps } from "formik/dist/types"; import { getFilesystemVolumeFormFields, + getVolumeConfigKeys, getVolumeKey, getZfsVolumeFormFields, } from "util/storageVolume"; @@ -29,6 +30,7 @@ import { } from "types/storage"; import { slugify } from "util/slugify"; import { driversWithFilesystemSupport } from "util/storageOptions"; +import { getUnhandledKeyValues } from "util/formFields"; export interface StorageVolumeFormValues { name: string; @@ -59,9 +61,14 @@ export interface StorageVolumeFormValues { export const volumeFormToPayload = ( values: StorageVolumeFormValues, project: string, + volume?: LxdStorageVolume, ): LxdStorageVolume => { const hasValidSize = values.size?.match(/^\d/); - return { + const unhandledVolumeConfigs = getUnhandledKeyValues( + volume?.config || {}, + getVolumeConfigKeys(), + ); + const payload = { name: values.name, config: { size: hasValidSize ? values.size : undefined, @@ -79,6 +86,7 @@ export const volumeFormToPayload = ( [getVolumeKey("zfs_remove_snapshots")]: values.zfs_remove_snapshots, [getVolumeKey("zfs_use_refquota")]: values.zfs_use_refquota, [getVolumeKey("zfs_reserve_space")]: values.zfs_reserve_space, + ...unhandledVolumeConfigs, }, project, type: values.volumeType, @@ -88,6 +96,17 @@ export const volumeFormToPayload = ( created_at: "", pool: values.pool, }; + + const allPayloadKeys = Object.keys(payload); + const unhandledVolumeMainConfigs = getUnhandledKeyValues( + volume || {}, + new Set(allPayloadKeys), + ); + const payLoadWithUnhandledConfigs = { + ...payload, + ...unhandledVolumeMainConfigs, + }; + return payLoadWithUnhandledConfigs; }; export const getFormProps = ( diff --git a/src/types/storage.d.ts b/src/types/storage.d.ts index c247903b08..abeb5b433a 100644 --- a/src/types/storage.d.ts +++ b/src/types/storage.d.ts @@ -1,3 +1,5 @@ +import { LxdConfigPair } from "./config"; + export interface LxdStoragePool { config: { size?: string; @@ -38,7 +40,7 @@ export interface LxdStorageVolume { "zfs.use_refquota"?: string; "zfs.reserve_space"?: string; size?: string; - }; + } & LxdConfigPair; content_type: LxdStorageVolumeContentType; created_at: string; description: string; diff --git a/src/util/formFields.tsx b/src/util/formFields.tsx index 8be8cdf3fa..3f576d1789 100644 --- a/src/util/formFields.tsx +++ b/src/util/formFields.tsx @@ -3,9 +3,15 @@ import { LxdInstance } from "types/instance"; import { OptionHTMLAttributes } from "react"; import { LxdConfigPair } from "types/config"; import { LxdProject } from "types/project"; +import { LxdStorageVolume } from "types/storage"; export const getUnhandledKeyValues = ( - item: LxdConfigPair | LxdInstance | LxdProfile | LxdProject, + item: + | LxdConfigPair + | LxdInstance + | LxdProfile + | LxdProject + | LxdStorageVolume, handledKeys: Set, ) => { return Object.fromEntries( diff --git a/src/util/storageVolume.tsx b/src/util/storageVolume.tsx index 2f8b3ee221..2977c3ea81 100644 --- a/src/util/storageVolume.tsx +++ b/src/util/storageVolume.tsx @@ -32,6 +32,7 @@ export const testDuplicateStorageVolumeName = ( }; const storageVolumeFormFieldToPayloadName: Record = { + size: "size", security_shifted: "security.shifted", security_unmapped: "security.unmapped", snapshots_expiry: "snapshots.expiry", @@ -62,12 +63,16 @@ export const getZfsVolumeFormFields = (): (keyof StorageVolumeFormValues)[] => { }; export const getVolumeKey = (key: string): string => { - if (Object.keys(storageVolumeFormFieldToPayloadName).includes(key)) { + if (key in storageVolumeFormFieldToPayloadName) { return storageVolumeFormFieldToPayloadName[key]; } return key; }; +export const getVolumeConfigKeys = (): Set => { + return new Set(Object.values(storageVolumeFormFieldToPayloadName)); +}; + export const renderVolumeType = (volume: LxdStorageVolume): string => { return volume.type === "virtual-machine" ? "VM"