diff --git a/charts/kubedbcom-clickhouse-editor-options/ui/create-ui.yaml b/charts/kubedbcom-clickhouse-editor-options/ui/create-ui.yaml index 0249137ff4..906a70164f 100644 --- a/charts/kubedbcom-clickhouse-editor-options/ui/create-ui.yaml +++ b/charts/kubedbcom-clickhouse-editor-options/ui/create-ui.yaml @@ -301,6 +301,57 @@ step: label: Configuration schema: schema/properties/spec/properties/configuration type: textarea + - if: + name: isToggleOn|pointInTimeRecovery + type: function + init: + type: func + value: getDefault|pointInTimeRecovery + label: Point in-time Recovery? + schema: temp/recovery + type: switch + - elements: + - label: "" + subtitle: Configure point-in-time recovery to restore your database to a specific + moment. Specify the source database namespace, name, and the exact timestamp + for recovery. + type: label-element + - elements: + - forceRequired: true + label: Namespace + schema: temp/refNamespace + type: input + validation: + type: required + watcher: + func: setPointInTimeRecovery + paths: + - temp/refNamespace + - label: Name + schema: temp/refDBName + type: input + validation: + type: required + watcher: + func: setPointInTimeRecovery + paths: + - temp/refDBName + showLabels: true + type: horizontal-layout + - customClass: mt-10 + label: Recovery Timestamp + schema: schema/properties/spec/properties/init/properties/archiver/properties/recoveryTimestamp + type: date-time + watcher: + func: onTimestampChange + paths: + - schema/properties/spec/properties/init/properties/archiver/properties/recoveryTimestamp + if: + name: showRecovery + type: function + label: Point in-time Recovery + showLabels: true + type: block-layout - if: name: isToggleOn|deployment type: function @@ -377,6 +428,28 @@ step: func: onBackupSwitch paths: - temp/backup + - elements: + - disable: + name: showArchiverAlert + watchPaths: + - schema/spec/admin/storageClasses/default + - schema/spec/mode + label: Enable Archiver? + schema: schema/properties/spec/properties/admin/properties/archiver/properties/enable/properties/default + type: switch + watcher: + func: onArchiverChange + paths: + - schema/properties/spec/properties/admin/properties/archiver/properties/enable/properties/default + - if: + name: showArchiverAlert + type: function + label: The selected StorageClass does not support Archiver + type: warning + if: + name: showArchiver + type: function + type: block-layout - elements: - if: name: isToggleOn|tls diff --git a/charts/kubedbcom-clickhouse-editor-options/ui/functions.js b/charts/kubedbcom-clickhouse-editor-options/ui/functions.js index 948b72f14c..122d4649b3 100644 --- a/charts/kubedbcom-clickhouse-editor-options/ui/functions.js +++ b/charts/kubedbcom-clickhouse-editor-options/ui/functions.js @@ -1308,6 +1308,121 @@ export const useFunc = (model) => { return (val && expected === 'true') || (!val && expected === 'false') } + function showRecovery() { + // watchDependency('discriminator#/recovery') + const isRecoveryOn = getValue(discriminator, '/recovery') || '' + return isRecoveryOn + } + + async function setPointInTimeRecovery() { + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const refNamespace = getValue(discriminator, '/refNamespace') + const refDBName = getValue(discriminator, '/refDBName') + + try { + const repositoriesUrl = `clusters/${owner}/${cluster}/proxy/storage.kubestash.com/v1alpha1/namespaces/${refNamespace}/repositories/${refDBName}-full` + const snapshotsUrl = `clusters/${owner}/${cluster}/proxy/storage.kubestash.com/v1alpha1/namespaces/${refNamespace}/snapshots/${refDBName}-incremental-snapshot` + const repositoriesResp = await axios.get(repositoriesUrl) + const snapshotsResp = await axios.get(snapshotsUrl) + + commit('wizard/model$update', { + path: `/spec/init/archiver/encryptionSecret/name`, + value: repositoriesResp.data?.spec.encryptionSecret.name, + force: true, + }) + commit('wizard/model$update', { + path: `/spec/init/archiver/encryptionSecret/namespace`, + value: repositoriesResp.data?.spec.encryptionSecret.namespace, + force: true, + }) + commit('wizard/model$update', { + path: `/spec/init/archiver/fullDBRepository/name`, + value: `${refDBName}-full`, + force: true, + }) + commit('wizard/model$update', { + path: `/spec/init/archiver/fullDBRepository/namespace`, + value: `${refNamespace}`, + force: true, + }) + commit('wizard/model$update', { + path: `/spec/init/archiver/manifestRepository/name`, + value: `${refDBName}-manifest`, + force: true, + }) + commit('wizard/model$update', { + path: `/spec/init/archiver/manifestRepository/namespace`, + value: `${refNamespace}`, + force: true, + }) + + const resp = getComponentLogStats(snapshotsResp.data) + + commit('wizard/model$update', { + path: `/spec/init/archiver/recoveryTimestamp`, + value: convertToUTC(resp?.end), + force: true, + }) + commit('wizard/model$update', { + path: `/minDate`, + value: convertToUTC(resp?.start), + force: true, + }) + commit('wizard/model$update', { + path: `/maxDate`, + value: convertToUTC(resp?.end), + force: true, + }) + } catch (e) { + pointIntimeError = + e.response?.data?.message || 'Invalid name / namespace for recovery timestamp' + commit('wizard/model$update', { + path: `/spec/init/archiver/recoveryTimestamp`, + value: '', + force: true, + }) + commit('wizard/model$update', { + path: `/minDate`, + value: '', + force: true, + }) + commit('wizard/model$update', { + path: `/maxDate`, + value: '', + force: true, + }) + commit('wizard/model$delete', '/spec/init/archiver/encryptionSecret') + commit('wizard/model$delete', '/spec/init/archiver/fullDBRepository') + commit('wizard/model$delete', '/spec/init/archiver/manifestRepository') + console.log(e) + } + } + + function convertToUTC(localTime) { + const date = new Date(localTime) + if (isNaN(date.getTime())) return + + const utcString = date.toISOString() + return utcString + } + + function onTimestampChange() { + const localTime = getValue(model, '/spec/init/archiver/recoveryTimestamp') + if (!localTime) return + + const utcString = convertToUTC(localTime) + + // Only update if the value is valid & not already in UTC format + if (utcString && localTime !== utcString) { + commit('wizard/model$update', { + path: '/spec/init/archiver/recoveryTimestamp', + value: utcString, + force: true, + }) + } + } + return { isExternallyManaged, showReferSecretSwitch, @@ -1367,5 +1482,8 @@ export const useFunc = (model) => { onModeChange, setBackup, getDefault, + setPointInTimeRecovery, + onTimestampChange, + showRecovery, } }