From 180c51f157dee694b7d308a59c32db97dd75cc33 Mon Sep 17 00:00:00 2001 From: Samiul Date: Thu, 12 Mar 2026 16:17:35 +0600 Subject: [PATCH 01/11] update security feature Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 78 +- .../ui/functions.js | 681 +++++++++--------- 2 files changed, 380 insertions(+), 379 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml index 08d06413e2..f44548ef63 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml @@ -1,41 +1,41 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form id: opscenter-security - title: steps.0.label + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded + # options: + # - text: Cert Manager + # value: cert-manager + # description: X.509 certificate management for Kubernetes and OpenShift + # - text: CA Cert CSI Driver + # value: ca-cert-csi-driver + # description: CSI Driver to mount ca-certs issued by cert-manager + # - text: Falco + # value: falco + # description: Container Native Runtime Security + # - text: Falco UI Server + # value: falco-ui-server + # description: Falco UI Server + # - text: Scanner + # value: scanner + # description: Scan docker image vulnerability and generate security report. + type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js index 2dc2cbf49b..479f8cc79a 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js @@ -1,389 +1,390 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} - -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} - -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} - -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} +const { axios, store, useOperator } = window.vueHelpers || {} + +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = + useOperator(model, store.state) + + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) + console.log({ name, feature, value }) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + console.log(enabledFeatureNames) + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + console.log({ featureBlock, configureMode, activeFeature }) + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + // console.log(resources) + console.log(resourceValuePath) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + console.log({ chart, sourceRef, version, targetNamespace, isEnabled, isManaged }) + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, + releaseName: featureName, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + let resources = {} -function returnFalse() { - return false -} + function returnFalse() { + return false + } + + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + console.log(isFeatureSetInstalled) + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + console.log(resourcesDefaultValues) + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) + console.log(allFeatureResourceValuePathNames) + + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } From c0782c7413db9faebdbb72ed9327ffe563a5346a Mon Sep 17 00:00:00 2001 From: Samiul Date: Fri, 13 Mar 2026 12:10:10 +0600 Subject: [PATCH 02/11] secret management Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 61 +- .../ui/functions.js | 671 +++++++++--------- .../ui/create-ui.yaml | 19 +- .../ui/functions.js | 12 +- 4 files changed, 358 insertions(+), 405 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml index 08d06413e2..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form id: opscenter-security - title: steps.0.label + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js index ddb0380125..42adac9d3e 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js @@ -1,391 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = + useOperator(model, store.state) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, + releaseName: featureName, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + let resources = {} -function returnFalse() { - return false -} + function returnFalse() { + return false + } + + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) + + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml index f44548ef63..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml @@ -20,22 +20,5 @@ step: watcher: func: checkIsResourceLoaded paths: - - temp/properties/isResourceLoaded - # options: - # - text: Cert Manager - # value: cert-manager - # description: X.509 certificate management for Kubernetes and OpenShift - # - text: CA Cert CSI Driver - # value: ca-cert-csi-driver - # description: CSI Driver to mount ca-certs issued by cert-manager - # - text: Falco - # value: falco - # description: Container Native Runtime Security - # - text: Falco UI Server - # value: falco-ui-server - # description: Falco UI Server - # - text: Scanner - # value: scanner - # description: Scan docker image vulnerability and generate security report. - + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js index 479f8cc79a..42adac9d3e 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js @@ -4,6 +4,9 @@ export const useFunc = (model) => { const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = useOperator(model, store.state) + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + // get specific feature details function getFeatureSetDetails() { const featureSets = storeGet('/cluster/featureSets/result') || [] @@ -35,7 +38,6 @@ export const useFunc = (model) => { function getFeaturePropertyValue(name, path) { const feature = getFeatureDetails(name) const value = storeGet(path, feature) - console.log({ name, feature, value }) return value } @@ -72,7 +74,6 @@ export const useFunc = (model) => { }) const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - console.log(enabledFeatureNames) return enabledFeatureNames } @@ -154,7 +155,6 @@ export const useFunc = (model) => { const featureBlock = storeGet('/route/query/activeBlock') || '' const configureMode = storeGet('/route/query/mode') || '' const activeFeature = storeGet('/route/query/activeFeature') || '' - console.log({ featureBlock, configureMode, activeFeature }) const allFeatureSetFeature = allFeatures.filter((item) => { @@ -215,8 +215,6 @@ export const useFunc = (model) => { allFeatures.forEach((item) => { const featureName = item?.metadata?.name || '' const resourceValuePath = getResourceValuePathFromFeature(item) - // console.log(resources) - console.log(resourceValuePath) if (enabledFeatures.includes(featureName)) { const featureSet = storeGet('/route/params/featureset') || '' @@ -228,7 +226,6 @@ export const useFunc = (model) => { const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') const isManaged = getFeaturePropertyValue(featureName, '/status/managed') - console.log({ chart, sourceRef, version, targetNamespace, isEnabled, isManaged }) if (isEnabled && !isManaged) { commit('wizard/model$delete', `/resources/${resourceValuePath}`) @@ -278,7 +275,6 @@ export const useFunc = (model) => { resources = { ...modelResources } const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') - console.log(isFeatureSetInstalled) if (isFeatureSetInstalled) { // get resources default values when featureset is installed @@ -299,7 +295,6 @@ export const useFunc = (model) => { url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` const { data } = await axios.get(url) const { resources: resourcesDefaultValues } = data || {} - console.log(resourcesDefaultValues) Object.keys(resourcesDefaultValues || {}).forEach((key) => { if (!resources[key]) { @@ -322,7 +317,6 @@ export const useFunc = (model) => { const allFeatureResourceValuePathNames = allFeatures.map((feature) => getResourceValuePathFromFeature(feature), ) - console.log(allFeatureResourceValuePathNames) Object.keys(modelResources).forEach((modelResourcePath) => { if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { From c1be7c9e3cfc6c0b15aa5ccedfa24cb22abd783a Mon Sep 17 00:00:00 2001 From: Samiul Date: Fri, 13 Mar 2026 14:46:43 +0600 Subject: [PATCH 03/11] datastore feature form Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 88 +- .../ui/functions.js | 921 +++++++++--------- .../ui/functions.js | 15 +- .../ui/functions.js | 21 +- 4 files changed, 517 insertions(+), 528 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml index 7b00af100b..0f6911c443 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml @@ -1,51 +1,39 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - enabledTypes: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - fetch: checkIsResourceLoaded - if: hideThisElement - type: input - - fetch: getDatabaseTypes - if: isKubedbSelected - label: - text: labels.select_db_types - onChange: onTypeUpdate - schema: - $ref: discriminator#/properties/enabledTypes - type: multiselect - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-datastore - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: select + customClass: mt-16 + multiple: true + schema: temp/properties/enabledTypes + label: Select Database Types + loader: getDatabaseTypes + init: + type: func + value: getEnabledTypes + if: + type: function + name: isKubedbSelected + watcher: + func: onTypeUpdate + paths: + - temp/properties/enabledTypes + - type: info + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js index ef06c1d3b8..3f6275bf26 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js @@ -1,525 +1,530 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} - -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} - -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} - -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} - -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) - - const modelValue = getValue(model, path) - return modelValue === value -} - -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} +const { axios, store, useOperator } = window.vueHelpers || {} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = + useOperator(model, store.state) + + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + setDiscriminatorValue('/enabledTypes', [ + 'Elasticsearch', + 'Kafka', + 'MariaDB', + 'MongoDB', + 'MySQL', + 'Postgres', + 'Redis', + ]) + let resources = {} + + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -let resources = {} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } - // for OCM + function isEqualToModelPathValue(path, value) { + watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + if (requiredFeatures.includes(featureName)) return true + else return false + } -function generatePresetValued(featureName, featureSet, storeGet) { - const featureDetails = getFeatureDetails(storeGet, featureName) - const resourceValuePath = getResourceValuePathFromFeature(featureDetails) - const chart = featureDetails?.spec?.chart?.name || '' - const targetNamespace = featureDetails?.spec?.chart?.namespace || '' - const sourceRef = featureDetails?.spec?.chart?.sourceRef - const version = featureDetails?.spec?.chart?.version + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - return { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function generatePresetValued(featureName, featureSet) { + const featureDetails = getFeatureDetails(featureName) + const resourceValuePath = getResourceValuePathFromFeature(featureDetails) + const chart = featureDetails?.spec?.chart?.name || '' + const targetNamespace = featureDetails?.spec?.chart?.namespace || '' + const sourceRef = featureDetails?.spec?.chart?.sourceRef + const version = featureDetails?.spec?.chart?.version + + return { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, - }, + } } -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - const allFeatures = storeGet('/cluster/features/result') || [] + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + const featureSet = storeGet('/route/params/featureset') || '' + + if (enabledFeatures.includes(featureName)) { + const featureDetails = getFeatureDetails(featureName) + const isEnabled = featureDetails?.status?.enabled || false + const isManaged = featureDetails?.status?.managed || false + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + const value = generatePresetValued(featureName, featureSet) + const path = `/resources/${resourceValuePath}` + commit('wizard/model$update', { + path: path, + value: value, + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } + }) - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) - const featureSet = storeGet('/route/params/featureset') || '' + const enabledTypes = getValue(discriminator, '/enabledTypes') || [] + typeConvert(enabledTypes) + } - if (enabledFeatures.includes(featureName)) { - const featureDetails = getFeatureDetails(storeGet, featureName) - const isEnabled = featureDetails?.status?.enabled || false - const isManaged = featureDetails?.status?.managed || false + function returnFalse() { + return false + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - const value = generatePresetValued(featureName, featureSet, storeGet) - const path = `/resources/${resourceValuePath}` - commit('wizard/model$update', { - path: path, - value: value, - force: true, - }) - } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) } - }) + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) - const enabledTypes = getValue(discriminator, '/enabledTypes') || [] - typeConvert(commit, enabledTypes, storeGet) -} + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -function returnFalse() { - return false -} + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) + } + }) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') + setDiscriminatorValue('/isResourceLoaded', true) + } - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, } }) + + return options || [] } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - const resource = getValue(model, '/metadata/resource') - commit('wizard/model$update', { - path: '/metadata/resource', - value: { - ...resource, - name: isFeatureSetInstalled ? 'features' : 'featuresets', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() } - }) - return options || [] -} - -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} - -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) } -} -function isKubedbSelected({ getValue, discriminator, watchDependency, commit, storeGet }) { - watchDependency('discriminator#/enabledFeatures') - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - const isSelected = enabledFeatures?.includes('kubedb') - - // if not selected return false and remove data - if (!isSelected) { - commit('wizard/model$delete', 'resources/helmToolkitFluxcdIoHelmRelease_kubedb') - return false - } + function isKubedbSelected() { + // watchDependency('discriminator#/enabledFeatures') + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + const isSelected = enabledFeatures?.includes('kubedb') - const kubedbFeatur = getFeatureDetails(storeGet, 'kubedb') - if (kubedbFeatur) { - const isEnabled = kubedbFeatur?.status?.enabled || false - const isManaged = kubedbFeatur?.status?.managed || false - // const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - // const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') - if (isEnabled && !isManaged) { + // if not selected return false and remove data + if (!isSelected) { commit('wizard/model$delete', 'resources/helmToolkitFluxcdIoHelmRelease_kubedb') return false } + + const kubedbFeatur = getFeatureDetails('kubedb') + if (kubedbFeatur) { + const isEnabled = kubedbFeatur?.status?.enabled || false + const isManaged = kubedbFeatur?.status?.managed || false + // const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') + // const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + if (isEnabled && !isManaged) { + commit('wizard/model$delete', 'resources/helmToolkitFluxcdIoHelmRelease_kubedb') + return false + } + } + return true } - return true -} -let allAvailableTypes = [ - 'Cassandra', - 'ClickHouse', - 'Druid', - 'Elasticsearch', - 'FerretDB', - 'Hazelcast', - 'Ignite', - 'Kafka', - 'MariaDB', - 'Memcached', - 'MSSQLServer', - 'MongoDB', - 'MySQL', - 'Oracle', - 'PerconaXtraDB', - 'PgBouncer', - 'Pgpool', - 'Postgres', - 'ProxySQL', - 'RabbitMQ', - 'Redis', - 'Singlestore', - 'Solr', - 'ZooKeeper', -] -let data = {} -let isFetching = 'stale' -async function getDatabaseTypes({ - setDiscriminatorValue, - discriminator, - commit, - storeGet, - getValue, - axios, -}) { - let enabledTypes = ['Elasticsearch', 'Kafka', 'MariaDB', 'MongoDB', 'MySQL', 'Postgres', 'Redis'] - const owner = storeGet('/route/params/user') || '' - const cluster = storeGet('/route/params/cluster') || '' - const spoke = storeGet('/route/params/spoke') - const getRoute = storeGet('/route') - - if (isFetching === 'success') { - enabledTypes = getValue(discriminator, '/enabledTypes') || [] - } else if (isFetching !== 'pending') { - try { - isFetching = 'pending' - - const clusterset = getRoute.fullPath.includes('/clustersets/') - ? getRoute.fullPath.split('/clustersets/')[1].split('/')[0] - : null - - let url = clusterset - ? `/clusters/${owner}/${cluster}/db-status?clusterset=${clusterset}` - : `/clusters/${owner}/${cluster}/db-status` - if (spoke) url = `/clusters/${owner}/${spoke}/db-status` - - const resp = await axios.get(url) - - data = resp?.data - isFetching = 'success' - if (Object.keys(data).length) { - enabledTypes = [] - allAvailableTypes = [] - for (const [key, value] of Object.entries(data)) { - if (value === true) enabledTypes.push(key) - allAvailableTypes.push(key) + let allAvailableTypes = [ + 'Cassandra', + 'ClickHouse', + 'Druid', + 'Elasticsearch', + 'FerretDB', + 'Hazelcast', + 'Ignite', + 'Kafka', + 'MariaDB', + 'Memcached', + 'MSSQLServer', + 'MongoDB', + 'MySQL', + 'Oracle', + 'PerconaXtraDB', + 'PgBouncer', + 'Pgpool', + 'Postgres', + 'ProxySQL', + 'RabbitMQ', + 'Redis', + 'Singlestore', + 'Solr', + 'ZooKeeper', + ] + let data = {} + let isFetching = 'stale' + let enabledTypes = [] + + async function databaseLoader() { + const owner = storeGet('/route/params/user') || '' + const cluster = storeGet('/route/params/cluster') || '' + const spoke = storeGet('/route/params/spoke') + const getRoute = storeGet('/route') + + if (isFetching === 'success') { + enabledTypes = getValue(discriminator, '/enabledTypes') || [] + } else if (isFetching !== 'pending') { + try { + isFetching = 'pending' + + const clusterset = getRoute.fullPath.includes('/clustersets/') + ? getRoute.fullPath.split('/clustersets/')[1].split('/')[0] + : null + + let url = clusterset + ? `/clusters/${owner}/${cluster}/db-status?clusterset=${clusterset}` + : `/clusters/${owner}/${cluster}/db-status` + if (spoke) url = `/clusters/${owner}/${spoke}/db-status` + + const resp = await axios.get(url) + + data = resp?.data + isFetching = 'success' + if (Object.keys(data).length) { + enabledTypes = [] + allAvailableTypes = [] + for (const [key, value] of Object.entries(data)) { + if (value === true) enabledTypes.push(key) + allAvailableTypes.push(key) + } } + } catch (e) { + console.log(e) } - } catch (e) { - console.log(e) + } else { + enabledTypes = ['Elasticsearch', 'Kafka', 'MariaDB', 'MongoDB', 'MySQL', 'Postgres', 'Redis'] + } + setDiscriminatorValue('/enabledTypes', enabledTypes) + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + const isSelected = enabledFeatures?.includes('kubedb') + if (isSelected) { + typeConvert(enabledTypes) } - } else { - enabledTypes = ['Elasticsearch', 'Kafka', 'MariaDB', 'MongoDB', 'MySQL', 'Postgres', 'Redis'] } - setDiscriminatorValue('/enabledTypes', enabledTypes) - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - const isSelected = enabledFeatures?.includes('kubedb') - if (isSelected) { - typeConvert(commit, enabledTypes, storeGet) + + async function getDatabaseTypes() { + return allAvailableTypes } - return allAvailableTypes -} -function onTypeUpdate({ discriminator, commit, getValue, storeGet }) { - const enabledTypes = getValue(discriminator, '/enabledTypes') || [] - typeConvert(commit, enabledTypes, storeGet) -} + function onTypeUpdate() { + const enabledTypes = getValue(discriminator, '/enabledTypes') || [] + typeConvert(enabledTypes) + } -function typeConvert(commit, enabledTypes, storeGet) { - let convertFromArray = {} - allAvailableTypes?.forEach((item) => { - convertFromArray[item] = enabledTypes ? enabledTypes.includes(item) : false - }) - - const kubedbValue = resources['helmToolkitFluxcdIoHelmRelease_kubedb'] - if (kubedbValue) { - const featureSet = storeGet('/route/params/featureset') || '' - const formattedValue = generatePresetValued('kubedb', featureSet, storeGet) - formattedValue.spec.values.global.featureGates = convertFromArray - commit('wizard/model$update', { - path: 'resources/helmToolkitFluxcdIoHelmRelease_kubedb', - value: formattedValue, - force: true, + function typeConvert(enabledTypes) { + let convertFromArray = {} + allAvailableTypes?.forEach((item) => { + convertFromArray[item] = enabledTypes ? enabledTypes.includes(item) : false }) + + const kubedbValue = resources['helmToolkitFluxcdIoHelmRelease_kubedb'] + if (kubedbValue) { + const featureSet = storeGet('/route/params/featureset') || '' + const formattedValue = generatePresetValued('kubedb', featureSet, storeGet) + formattedValue.spec.values.global.featureGates = convertFromArray + commit('wizard/model$update', { + path: 'resources/helmToolkitFluxcdIoHelmRelease_kubedb', + value: formattedValue, + force: true, + }) + } + + return convertFromArray } - return convertFromArray -} + function getEnabledTypes() { + const enabledTypes = getValue(discriminator, '/enabledTypes') || [] + console.log(enabledTypes) -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, - isKubedbSelected, - getDatabaseTypes, - onTypeUpdate, - returnFalse, + return enabledTypes + } + + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + isKubedbSelected, + getDatabaseTypes, + onTypeUpdate, + returnFalse, + getEnabledTypes, + databaseLoader, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js index 42adac9d3e..799d2d3759 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js @@ -1,11 +1,14 @@ const { axios, store, useOperator } = window.vueHelpers || {} export const useFunc = (model) => { - const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = - useOperator(model, store.state) + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) setDiscriminatorValue('/enabledFeatures', []) setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} // get specific feature details function getFeatureSetDetails() { @@ -49,7 +52,7 @@ export const useFunc = (model) => { } function isEqualToModelPathValue(path, value) { - watchDependency(`model#${path}`) + // watchDependency(`model#${path}`) const modelValue = getValue(model, path) return modelValue === value @@ -187,7 +190,7 @@ export const useFunc = (model) => { } function disableFeatures() { - watchDependency('discriminator#/isResourceLoaded') + // watchDependency('discriminator#/isResourceLoaded') const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true @@ -264,8 +267,6 @@ export const useFunc = (model) => { }) } - let resources = {} - function returnFalse() { return false } @@ -360,7 +361,7 @@ export const useFunc = (model) => { // this computed's main purpose is to watch isResourceLoaded flag // and fire the onEnabledFeatureChange function when it's true function checkIsResourceLoaded() { - watchDependency('discriminator#/isResourceLoaded') + // watchDependency('discriminator#/isResourceLoaded') const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (isResourceLoaded) { onEnabledFeaturesChange() diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js index 42adac9d3e..135da482fc 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js @@ -1,11 +1,14 @@ const { axios, store, useOperator } = window.vueHelpers || {} export const useFunc = (model) => { - const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = - useOperator(model, store.state) + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) setDiscriminatorValue('/enabledFeatures', []) setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} // get specific feature details function getFeatureSetDetails() { @@ -42,14 +45,8 @@ export const useFunc = (model) => { return value } - // helper function to get nested property value from feature - function getFeatureProperty(featureName, propertyPath) { - const feature = getFeatureDetails(featureName) - return storeGet(propertyPath, feature) - } - function isEqualToModelPathValue(path, value) { - watchDependency(`model#${path}`) + // watchDependency(`model#${path}`) const modelValue = getValue(model, path) return modelValue === value @@ -187,7 +184,7 @@ export const useFunc = (model) => { } function disableFeatures() { - watchDependency('discriminator#/isResourceLoaded') + // watchDependency('discriminator#/isResourceLoaded') const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true @@ -264,8 +261,6 @@ export const useFunc = (model) => { }) } - let resources = {} - function returnFalse() { return false } @@ -360,7 +355,7 @@ export const useFunc = (model) => { // this computed's main purpose is to watch isResourceLoaded flag // and fire the onEnabledFeatureChange function when it's true function checkIsResourceLoaded() { - watchDependency('discriminator#/isResourceLoaded') + // watchDependency('discriminator#/isResourceLoaded') const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (isResourceLoaded) { onEnabledFeaturesChange() From cfbca6771bfa8333181047c31e58a341ec4fc5b7 Mon Sep 17 00:00:00 2001 From: Samiul Date: Fri, 13 Mar 2026 14:48:17 +0600 Subject: [PATCH 04/11] linting Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/functions.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js index 3f6275bf26..cd4343216e 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js @@ -1,7 +1,9 @@ const { axios, store, useOperator } = window.vueHelpers || {} export const useFunc = (model) => { - const { getValue, setDiscriminatorValue, commit, storeGet, discriminator, watchDependency } = - useOperator(model, store.state) + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) setDiscriminatorValue('/enabledFeatures', []) setDiscriminatorValue('/isResourceLoaded', false) @@ -43,7 +45,7 @@ export const useFunc = (model) => { } function isEqualToModelPathValue(path, value) { - watchDependency(`model#${path}`) + // watchDependency(`model#${path}`) const modelValue = getValue(model, path) return modelValue === value @@ -362,7 +364,7 @@ export const useFunc = (model) => { // this computed's main purpose is to watch isResourceLoaded flag // and fire the onEnabledFeatureChange function when it's true function checkIsResourceLoaded() { - watchDependency('discriminator#/isResourceLoaded') + // watchDependency('discriminator#/isResourceLoaded') const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (isResourceLoaded) { onEnabledFeaturesChange() From c7b87315e6cdeb91e9ed3517ecb5d57fe7b0b265 Mon Sep 17 00:00:00 2001 From: Samiul Date: Fri, 13 Mar 2026 15:22:52 +0600 Subject: [PATCH 05/11] update all features chart Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 654 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 655 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 654 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 671 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 669 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 655 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 721 +++++++++--------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 669 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 668 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 671 ++++++++-------- .../ui/create-ui.yaml | 61 +- .../ui/functions.js | 667 ++++++++-------- .../ui/functions.js | 1 - .../ui/functions.js | 1 - .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 669 ++++++++-------- .../ui/create-ui.yaml | 63 +- .../ui/functions.js | 670 ++++++++-------- .../ui/create-ui.yaml | 355 +-------- .../ui/functions.js | 708 ++++++++--------- 30 files changed, 5012 insertions(+), 5563 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml index 2374876a32..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: dbaas-capa - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js index f1bf9756cc..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js @@ -1,364 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} - -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +const { axios, store, useOperator } = window.vueHelpers || {} -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } - const modelValue = getValue(model, path) - return modelValue === value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { - return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) - ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - return enabledFeatureNames -} + const modelValue = getValue(model, path) + return modelValue === value + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) + ) + }) - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) - } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName } + + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } -} -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + return enabledFeatureNames + } - if (requiredFeatures.includes(featureName)) return true - else return false -} + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) + } - const allFeatures = storeGet('/cluster/features/result') || [] + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } + } else { + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } + } + } - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + if (requiredFeatures.includes(featureName)) return true + else return false + } + + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } + + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - - let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml index 7eaa847ca2..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: dbaas-capg - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js index fe2b3ff976..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js @@ -1,365 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} - -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +const { axios, store, useOperator } = window.vueHelpers || {} -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } - const modelValue = getValue(model, path) - return modelValue === value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { - return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) - ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - return enabledFeatureNames -} + const modelValue = getValue(model, path) + return modelValue === value + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) + ) + }) - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) - } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName } + + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } -} -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + return enabledFeatureNames + } - if (requiredFeatures.includes(featureName)) return true - else return false -} + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) + } - const allFeatures = storeGet('/cluster/features/result') || [] + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } + } else { + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } + } + } - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + if (requiredFeatures.includes(featureName)) return true + else return false + } + + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } + + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - - let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml index afc9c3ac33..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: dbaas-capz - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js index f1bf9756cc..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js @@ -1,364 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} - -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +const { axios, store, useOperator } = window.vueHelpers || {} -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } - const modelValue = getValue(model, path) - return modelValue === value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { - return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) - ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - return enabledFeatureNames -} + const modelValue = getValue(model, path) + return modelValue === value + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) + ) + }) - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) - } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName } + + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } -} -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + return enabledFeatureNames + } - if (requiredFeatures.includes(featureName)) return true - else return false -} + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) + } - const allFeatures = storeGet('/cluster/features/result') || [] + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } + } else { + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } + } + } - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + if (requiredFeatures.includes(featureName)) return true + else return false + } + + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } + + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - - let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml index 349e427996..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js index caa098e29e..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js @@ -1,391 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' + return value + } - // for OCM + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + const modelValue = getValue(model, path) + return modelValue === value } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - - const spoke = storeGet('route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml index afc9c3ac33..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: dbaas-capz - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js index 2dc2cbf49b..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js @@ -1,389 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml index 349e427996..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js index fe2b3ff976..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js @@ -1,365 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} - -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +const { axios, store, useOperator } = window.vueHelpers || {} -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } - const modelValue = getValue(model, path) - return modelValue === value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { - return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) - ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - return enabledFeatureNames -} + const modelValue = getValue(model, path) + return modelValue === value + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) + ) + }) - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) - } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName } + + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } -} -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + return enabledFeatureNames + } - if (requiredFeatures.includes(featureName)) return true - else return false -} + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) + } - const allFeatures = storeGet('/cluster/features/result') || [] + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } + } else { + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } + } + } - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + if (requiredFeatures.includes(featureName)) return true + else return false + } + + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } + + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - - let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml index 349e427996..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js index a7af42412a..f9e7d3455c 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js @@ -1,422 +1,415 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets?.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -function getFeatureSetDetailsOcm(storeGet) { - const featureSets = storeGet('/ocm/featureSet/result') +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets?.find((item) => item?.name === featureSetName) - return featureSet -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} - -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + return value + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - // for OCM - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended || item.featureBlock === featureBlock - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) + }) + + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } + + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - return enabledFeatureNames -} + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' - const getRoute = storeGet('/route') - - // extreme special case for OCM featureSet - if (featureSet === 'opscenter-core' && getRoute?.fullPath?.includes('/hubs/')) { - return ['flux2', 'kube-ui-server', 'license-proxyserver', 'opscenter-features'] + return enabledFeatureNames } - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + const getRoute = storeGet('/route') + + // extreme special case for OCM featureSet + if (featureSet === 'opscenter-core' && getRoute?.fullPath?.includes('/hubs/')) { + return ['flux2', 'kube-ui-server', 'license-proxyserver', 'opscenter-features'] + } - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) - } + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const getRoute = storeGet('/route') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const featureName = itemCtx.value - const featureName = itemCtx.value + let featureSet = {} + let requiredFeatures = [] + if (getRoute.fullPath.includes('/hubs/')) { + featureSet = getFeatureSetDetailsOcm() + requiredFeatures = featureSet?.requiredFeatures || [] + } else { + featureSet = getFeatureSetDetails() + requiredFeatures = featureSet?.spec?.requiredFeatures || [] + } - let featureSet = {} - let requiredFeatures = [] - if (getRoute.fullPath.includes('/hubs/')) { - featureSet = getFeatureSetDetailsOcm(storeGet) - requiredFeatures = featureSet?.requiredFeatures || [] - } else { - featureSet = getFeatureSetDetails(storeGet) - requiredFeatures = featureSet?.spec?.requiredFeatures || [] + if (requiredFeatures.includes(featureName)) return true + else return false } - if (requiredFeatures.includes(featureName)) return true - else return false -} - -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function checkSpecialOcmCase(storeGet, featureName) { - const getRoute = storeGet('/route') - const specialNames = ['flux2', 'license-proxyserver'] - if (getRoute?.fullPath?.includes('/hubs/') && specialNames.includes(featureName)) return false - - return true -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - - const allFeatures = storeGet('/cluster/features/result') || [] - - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) - - if (enabledFeatures.includes(featureName) && checkSpecialOcmCase(storeGet, featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) - - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName) && checkSpecialOcmCase(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) + }) + } + + function returnFalse() { + return false + } + + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) } - }) -} + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) -let resources = {} + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -function returnFalse() { - return false -} + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) + } + }) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + setDiscriminatorValue('/isResourceLoaded', true) + } + + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, } }) + + return options || [] } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() } - }) + } - return options || [] -} + function checkSpecialOcmCase(featureName) { + const getRoute = storeGet('/route') + const specialNames = ['flux2', 'license-proxyserver'] + if (getRoute?.fullPath?.includes('/hubs/') && specialNames.includes(featureName)) return false -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + return true + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + function getFeatureSetDetailsOcm() { + const featureSets = storeGet('/ocm/featureSet/result') + + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets?.find((item) => item?.name === featureSetName) + return featureSet } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, - checkSpecialOcmCase, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + checkSpecialOcmCase, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml index 30b57a5daa..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-cost - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js index 2dc2cbf49b..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js @@ -1,389 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml index 0c62457f53..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-networking - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js index b913198eaf..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js @@ -1,388 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml index 08663642cd..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - type: single-step-form - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - id: opscenter-monitoring - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js index bf4f0f30b3..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js @@ -1,391 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml index 08d06413e2..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form id: opscenter-security - title: steps.0.label + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js index ee408928f4..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js @@ -1,387 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js index 799d2d3759..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js @@ -255,7 +255,6 @@ export const useFunc = (model) => { }, }, targetNamespace, - releaseName: featureName, }, }, force: true, diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js index 135da482fc..3684fb1674 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js @@ -249,7 +249,6 @@ export const useFunc = (model) => { }, }, targetNamespace, - releaseName: featureName, }, }, force: true, diff --git a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml index 349e427996..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js index 2dc2cbf49b..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js @@ -1,389 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml index 349e427996..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml @@ -1,41 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js index 6c09e0ccdf..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js @@ -1,390 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - - if (requiredFeatures.includes(featureName)) return true - else return false -} -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - const allFeatures = storeGet('/cluster/features/result') || [] + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + function returnFalse() { + return false + } -function returnFalse() { - return false -} + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) - } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + setDiscriminatorValue('/isResourceLoaded', true) + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) - return options || [] -} + return options || [] + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } } -} -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml index f42dc9060b..2e5c8a4160 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml @@ -1,333 +1,24 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean - elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - - elements: - - elements: - - label: - text: caCert - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/cluster/properties/tls/properties/ca/properties/cert - type: textarea - - label: - text: caKey - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/cluster/properties/tls/properties/ca/properties/key - type: textarea - hideForm: true - label: - text: Cluster - show_label: true - type: single-step-form - - elements: - - label: - text: Nodeport Range - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/nodeportRange - type: input - - label: - text: Port Range - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/portRange - type: input - - element: - label: - text: External IP - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/externalIPs/items - type: input - label: - text: External IPs - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/externalIPs - type: list-input-form - - fetch: fetchEnum - label: - text: External Traffic Policy - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/externalTrafficPolicy - type: select - - fetch: fetchEnum - label: - text: Type - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/type - type: select - label: - text: Envoy Service Ports - show_label: true - type: single-step-form - - elements: - - label: - text: Envoy Gateway - type: label-element - - label: - text: enable Gateway Converter? - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/gateway/properties/gateway-converter/properties/enabled - type: switch - type: single-step-form - - elements: - - label: - text: Name - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/vaultServer/properties/name - type: input - - label: - text: Namespace - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/vaultServer/properties/namespace - type: input - hideForm: true - label: - text: Vault Server - show_label: true - type: single-step-form - - elements: - - elements: - - computed: returnProvider - fetch: fetchEnum - label: - text: Provider - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/provider - type: select - - elements: - - label: - text: Environment - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/environment - type: input - - label: - text: Hosted Zone Name - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/hostedZoneName - type: input - - label: - text: Resource Group Name - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/resourceGroupName - type: input - - label: - text: Service Principal App ID - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/servicePrincipalAppID - type: input - - inputType: password - label: - text: Service Principal App Password - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/servicePrincipalAppPassword - type: input - - label: - text: Subscription ID - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/subscriptionID - type: input - - label: - text: Tenant ID - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/tenantID - type: input - if: checkDnsProvider|azureDNS - label: - text: azureDNS - type: single-step-form - - elements: - - label: - text: GOOGLE PROJECT ID - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudDNS/properties/GOOGLE_PROJECT_ID - type: input - - label: - text: GOOGLE SERVICE ACCOUNT JSON KEY - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudDNS/properties/GOOGLE_SERVICE_ACCOUNT_JSON_KEY - type: input - if: checkDnsProvider|cloudDNS - label: - text: cloudDNS - type: single-step-form - - elements: - - label: - text: Base URL - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudflare/properties/baseURL - type: input - - label: - text: Token - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudflare/properties/token - type: input - if: checkDnsProvider|cloudflare - label: - text: cloudflare - type: single-step-form - - elements: - - label: - text: AWS Access Key ID - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_ACCESS_KEY_ID - type: input - - label: - text: AWS Region - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_REGION - type: input - - label: - text: AWS Secret Access Key - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_SECRET_ACCESS_KEY - type: input - if: checkDnsProvider|route53 - label: - text: route53 - type: single-step-form - label: - text: DNS - show_label: true - type: single-step-form - - label: - text: Host - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/host - type: input - - fetch: fetchEnum - label: - text: Host Type - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/hostType - type: select - - elements: - - fetch: fetchEnum - label: - text: Issuer - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/issuer - type: select - - elements: - - inputType: Email - label: - text: Email - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/acme/properties/email - type: input - - fetch: fetchEnum - label: - text: Solver - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/acme/properties/solver - type: select - if: checkIssuer|letsencrypt - label: - text: acme - type: single-step-form - - elements: - - label: - text: caCert - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/ca/properties/cert - type: textarea - - label: - text: caKey - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/ca/properties/key - type: textarea - if: checkIssuer|ca - label: - text: ca - type: single-step-form - - elements: - - label: - text: certificateCert - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/certificate/properties/cert - type: textarea - - label: - text: certificateKey - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/certificate/properties/key - type: textarea - if: checkIssuer|external - label: - text: certificate - type: single-step-form - label: - text: TLS - show_label: true - type: single-step-form - label: - text: Infra - show_label: true - type: single-step-form - - elements: - - label: - text: Skip GatewayPreset - type: label-element - - label: - text: Skip creating GatewayPreset ? - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/skipGatewayPreset - type: switch - type: single-step-form - if: isServiceGatewaySelected - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets - type: single-step-form - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-security + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js index 78ef75efe0..ed2a267831 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js @@ -1,432 +1,384 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets?.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = storeGet(path, featureSet) + return value + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = storeGet(path, feature) -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + return value + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' + // helper function to get nested property value from feature + function getFeatureProperty(featureName, propertyPath) { + const feature = getFeatureDetails(featureName) + return storeGet(propertyPath, feature) + } - // for OCM + function isEqualToModelPathValue(path, value) { + // watchDependency(`model#${path}`) - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') + const modelValue = getValue(model, path) + return modelValue === value + } - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - return enabledFeatureNames -} + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) + return enabledFeatureNames } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + function disableFeatures() { + // watchDependency('discriminator#/isResourceLoaded') - if (requiredFeatures.includes(featureName)) return true - else return false -} - -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const allFeatures = storeGet('/cluster/features/result') || [] - - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) - - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + if (requiredFeatures.includes(featureName)) return true + else return false + } - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + + const allFeatures = storeGet('/cluster/features/result') || [] + + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + + const targetNamespace = getFeaturePropertyValue(featureName, '/spec/chart/namespace') + const sourceRef = getFeaturePropertyValue(featureName, '/spec/chart/sourceRef') + const version = getFeaturePropertyValue(featureName, '/spec/chart/version') + + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) - } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} - -let resources = {} - -function returnFalse() { - return false -} - -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } }) } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + function returnFalse() { + return false + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('/route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) } - }) + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) - return options || [] -} + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) + } + }) -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + setDiscriminatorValue('/isResourceLoaded', true) } -} -function isServiceGatewaySelected({ watchDependency, discriminator, getValue }) { - watchDependency('discriminator#/enabledFeatures') - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - if (enabledFeatures?.find((service) => service === 'service-gateway-presets')) return true - else return false -} - -function checkDnsProvider({ watchDependency, model, getValue }, provider) { - watchDependency( - 'model#/resources/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/spec/values/infra/dns/provider', - ) - const selectedProvider = getValue( - model, - '/resources/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/spec/values/infra/dns/provider', - ) - return selectedProvider === provider -} + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) -function checkIssuer({ watchDependency, model, getValue }, issuer) { - watchDependency( - 'model#/resources/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/spec/values/infra/tls/issuer', - ) - const selectedIssuer = getValue( - model, - '/resources/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/spec/values/infra/tls/issuer', - ) - return selectedIssuer === issuer -} + return options || [] + } -function fetchEnum({ elementSchema }) { - return elementSchema.enum -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -function returnProvider() { - return 'none' -} + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + // watchDependency('discriminator#/isResourceLoaded') + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } + } -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, - isServiceGatewaySelected, - checkDnsProvider, - checkIssuer, - returnProvider, - fetchEnum, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + } } From fb48c9db0ce8236e08f58f947ec5faadf5189edb Mon Sep 17 00:00:00 2001 From: Samiul Date: Fri, 13 Mar 2026 15:29:36 +0600 Subject: [PATCH 06/11] fix db loader Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/functions.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js index cd4343216e..cc462bab12 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js @@ -331,6 +331,8 @@ export const useFunc = (model) => { }) setDiscriminatorValue('/isResourceLoaded', true) + + await databaseLoader() } function fetchFeatureSetOptions() { From 2c8d6681c7b039450fd68e68a77de13f6e82ae08 Mon Sep 17 00:00:00 2001 From: Samiul Date: Mon, 30 Mar 2026 12:12:54 +0600 Subject: [PATCH 07/11] update ids Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- .../ui/create-ui.yaml | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml index 2e5c8a4160..c5dd8bf80f 100644 --- a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: dbaas-capa elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml index 2e5c8a4160..210a6eadef 100644 --- a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: dbaas-capg elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml index 2e5c8a4160..f261b6bd17 100644 --- a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: dbaas-capz elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml index 2e5c8a4160..87af9ac052 100644 --- a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-core elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml index 2e5c8a4160..de02cc0a9d 100644 --- a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: crossplane elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml index 2e5c8a4160..b64bf58b16 100644 --- a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: ocm-hub elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml index 2e5c8a4160..87af9ac052 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-core elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml index 2e5c8a4160..b26c8e2024 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-cost elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml index 0f6911c443..a946952b1f 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-datastore elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml index 2e5c8a4160..e28d9609ae 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-networking elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml index 2e5c8a4160..19cc28e3dc 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-monitoring elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml index 2e5c8a4160..8fa137f59a 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-policy-management elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml index 2e5c8a4160..5141aa8c7d 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-secret-management elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml index 2e5c8a4160..2f37670832 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-storage elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml index 2e5c8a4160..fedd8ea8f8 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: opscenter-tools elements: - type: checkbox schema: temp/properties/enabledFeatures diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml index 2e5c8a4160..e0ea4e5b96 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml @@ -1,7 +1,7 @@ step: - loader: setReleaseNameAndNamespaceAndInitializeValues type: single-step-form - id: opscenter-security + id: saas-core elements: - type: checkbox schema: temp/properties/enabledFeatures From 6a34bbd2204d1b25a3170df779935916d4f91cb0 Mon Sep 17 00:00:00 2001 From: Samiul Date: Wed, 1 Apr 2026 10:32:39 +0600 Subject: [PATCH 08/11] update saas-core Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 217 +++++++++++++++++- .../ui/functions.js | 29 +++ 2 files changed, 245 insertions(+), 1 deletion(-) diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml index e0ea4e5b96..3d8e459df1 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml @@ -20,5 +20,220 @@ step: watcher: func: checkIsResourceLoaded paths: - - temp/properties/isResourceLoaded + - temp/properties/isResourceLoaded + - type: block-layout + if: + name: isServiceGatewaySelected + type: function + elements: + - type: block-layout + hideBlock: true + showLabels: true + label: Cluster + elements: + - label: caCert + type: textarea + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/cluster/properties/tls/properties/ca/properties/cert + - label: caKey + type: textarea + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/cluster/properties/tls/properties/ca/properties/key + - type: block-layout + showLabels: false + elements: + - label: Nodeport Range + type: input + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/nodeportRange + - label: Port Range + type: input + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/portRange + - type: array-item-form + label: External IPs + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/externalIPs + element: + type: input + label: External IP + - type: block-layout + label: Envoy Service Ports + showLabels: true + elements: + - type: select + label: External Traffic Policy + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/externalTrafficPolicy + - type: select + label: type + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/envoy/properties/service/properties/type + - type: switch + label: Enable Gateway Converter? + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/gateway/properties/gateway-converter/properties/enabled + - type: block-layout + label: Vault Server + showLabels: true + elements: + - type: input + label: Name + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/vaultServer/properties/name + - type: input + label: Namespace + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/vaultServer/properties/namespace + - type: block-layout + label: Infra + showLabels: true + elements: + - type: block-layout + label: DNS + showLabels: true + elements: + - type: select + label: provider + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/provider + - type: block-layout + label: Azure DNS + showLabels: true + if: + name: checkDnsProvider|azureDNS + type: function + elements: + - type: input + label: Environment + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/environment + - type: input + label: Hosted Zone Name + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/hostedZoneName + - type: input + label: Resource Group Name + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/resourceGroupName + - type: input + label: Service Principal App ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/servicePrincipalAppID + - type: input + label: Service Principal App Password + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/servicePrincipalAppPassword + - type: input + label: Subscription ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/subscriptionID + - type: input + label: Tenant ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/azureDNS/properties/tenantID + - type: block-layout + label: cloudDNS + if: + name: checkDnsProvider|cloudDNS + type: function + showLabels: true + elements: + - type: input + label: GOOGLE PROJECT ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudDNS/properties/GOOGLE_PROJECT_ID + - type: input + label: GOOGLE SERVICE ACCOUNT KEY (JSON) + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudDNS/properties/GOOGLE_SERVICE_ACCOUNT_JSON_KEY + - type: block-layout + label: cloudflare + if: + name: checkDnsProvider|cloudflare + type: function + showLabels: true + elements: + - type: input + label: Base URL + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudflare/properties/baseURL + - type: input + label: Token + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/cloudflare/properties/token + - type: block-layout + label: route53 + if: + name: checkDnsProvider|route53 + type: function + showLabels: true + elements: + - type: input + label: AWS Access Key ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_ACCESS_KEY_ID + - type: input + label: AWS Region + forceRequired: true + schema: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_REGION + - type: input + label: AWS Secret Access Key + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_SECRET_ACCESS_KEY + - type: input + label: Host + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/host + - type: select + label: Host Type + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/hostType + - type: block-layout + label: TLS + showLabels: true + elements: + - type: select + label: Issuer + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/issuer + - type: block-layout + if: + name: checkIssuer|letsencrypt + type: function + label: acme + showLabels: true + elements: + - type: input + label: Email + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/acme/properties/email + - type: select + label: Solver + validation: + type: required + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/acme/properties/solver + - type: block-layout + if: + name: checkIssuer|ca + type: function + label: ca + showLabels: true + elements: + - type: textarea + label: caCert + validation: + type: required + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/ca/properties/cert + - type: textarea + label: caKey + validation: + type: required + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/ca/properties/key + - type: block-layout + label: certificate + if: + name: checkIssuer|external + type: function + showLabels: true + elements: + - type: textarea + label: Certificate Cert + validation: + type: required + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/certificate/properties/cert + - type: textarea + label: Certificate Key + validation: + type: required + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/tls/properties/certificate/properties/key + - type: switch + label: Skip creating GatewayPreset? + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/skipGatewayPreset type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js index ed2a267831..9741bf9aea 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js @@ -367,6 +367,31 @@ export const useFunc = (model) => { } } + function checkDnsProvider(provider) { + const selectedProvider = getValue( + model, + '/resources/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/spec/values/infra/dns/provider', + ) + return selectedProvider === provider + } + + function checkIssuer(issuer) { + const selectedIssuer = getValue( + model, + '/resources/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/spec/values/infra/tls/issuer', + ) + return selectedIssuer === issuer + } + + function isServiceGatewaySelected() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (enabledFeatures?.find((service) => service === 'service-gateway-presets')) return true + else return false + } + + function returnProvider() { + return 'none' + } return { hideThisElement, checkIsResourceLoaded, @@ -380,5 +405,9 @@ export const useFunc = (model) => { returnFalse, setReleaseNameAndNamespaceAndInitializeValues, fetchFeatureSetOptions, + isServiceGatewaySelected, + returnProvider, + checkDnsProvider, + checkIssuer, } } From 573f86c993714e9304b5c5dfc99f9f1edb03e376 Mon Sep 17 00:00:00 2001 From: "Md. Samiul Haque" Date: Wed, 1 Apr 2026 15:58:15 +0600 Subject: [PATCH 09/11] backup chart (#997) * wip backup Signed-off-by: samiul * update backup Signed-off-by: Samiul * customclass Signed-off-by: Samiul --------- Signed-off-by: samiul Signed-off-by: Samiul Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 503 +++----- .../ui/functions.js | 1046 ++++++++--------- 2 files changed, 703 insertions(+), 846 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml index be121bf4d2..db0bf99305 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml @@ -1,314 +1,195 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-backup + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + customClass: mt-24 + label: 'Note: Enabling a feature auto enables any prerequisite features' + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded + - type: block-layout + if: + name: isStashPreset + type: function elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - backupPresetType: - type: string - enabledFeatures: - type: array + - type: label-element + label: Preset Configuration + - type: block-layout + if: + name: presetType|kubestash + type: function + elements: + - type: select + label: Backend Provider + options: + - text: Azure Blob Storage + value: azure + - text: Google Cloud Service + value: gcs + - text: AWS S3 + value: s3 + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/provider + - type: block-layout + if: + name: providerType|s3 + type: function elements: - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - discriminator: - isFormOpen: - type: boolean + - type: input + label: Bucket + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/bucket + - type: input + label: End Point + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/endpoint + - type: input + label: Insecure TLS + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/insecureTLS + - type: input + label: Prefix + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/prefix + - type: input + label: Region + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/region + - type: switch + label: Enable Storage Secret? + init: + type: func + value: setStorageSecret + schema: temp/properties/s3 + watcher: + func: onAuthChange|s3 + paths: + - temp/properties/s3 + - type: block-layout + if: + name: authEnabled + type: function + label: Storage Secret elements: - - elements: - - elements: - - elements: - - label: - text: labels.backup.type - type: label-element - - computed: setTool - if: returnFalse - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/tool - type: input - - elements: - - elements: - - computed: setProvider - label: - text: labels.backend.provider - options: - - text: Azure Blob Storage - value: azure - - text: Google Cloud Service - value: gcs - - text: AWS S3 - value: s3 - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/provider - type: select - - elements: - - discriminator: - s3: - default: false - type: boolean - elements: - - label: - text: labels.backend.bucket - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/bucket - type: input - - label: - text: labels.backend.endPoint - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/endpoint - type: input - - label: - text: labels.backend.insecureTLS - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/insecureTLS - type: input - - label: - text: labels.backend.prefix - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/prefix - type: input - - label: - text: labels.backend.region - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec/properties/region - type: input - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/spec - type: single-step-form - - computed: setStorageSecret - label: - text: labels.kubestash.storageSecret.switch - onChange: onAuthChange|s3 - schema: - $ref: discriminator#/s3 - type: switch - - elements: - - label: - text: labels.backend.s3.access_key_id - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth/properties/AWS_ACCESS_KEY_ID - type: input - - label: - text: labels.backend.s3.secret_access_key - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth/properties/AWS_SECRET_ACCESS_KEY - type: input - - label: - text: labels.backend.s3.ca_cert_data - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth/properties/CA_CERT_DATA - type: input - if: authEnabled - label: - text: labels.kubestash.storageSecret.label - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth - show_label: true - type: single-step-form - if: providerType|s3 - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3 - type: single-step-form - - elements: - - discriminator: - azure: - default: false - type: boolean - elements: - - label: - text: labels.backend.container - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/spec/properties/container - type: input - - label: - text: labels.backend.max_connections - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/spec/properties/maxConnections - type: input - - label: - text: labels.backend.prefix - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/spec/properties/prefix - type: input - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/spec - type: single-step-form - - computed: setStorageSecret - label: - text: labels.kubestash.storageSecret.switch - onChange: onAuthChange|azure - schema: - $ref: discriminator#/azure - type: switch - - elements: - - label: - text: labels.backend.azure.account_name - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/auth/properties/AZURE_ACCOUNT_NAME - type: input - - label: - text: labels.backend.azure.account_key - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/auth/properties/AZURE_ACCOUNT_KEY - type: input - if: authEnabled - label: - text: labels.kubestash.storageSecret.label - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/auth - show_label: true - type: single-step-form - if: providerType|azure - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure - type: single-step-form - - elements: - - discriminator: - gcs: - default: false - type: boolean - elements: - - elements: - - label: - text: labels.backend.bucket - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec/properties/bucket - type: input - - label: - text: labels.backend.max_connections - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec/properties/maxConnections - type: input - - label: - text: labels.backend.prefix - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec/properties/prefix - type: input - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec - type: single-step-form - type: single-step-form - - computed: setStorageSecret - label: - text: labels.kubestash.storageSecret.switch - onChange: onAuthChange|gcs - schema: - $ref: discriminator#/gcs - type: switch - - elements: - - label: - text: labels.backend.gcs.project_id - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/auth/properties/GOOGLE_PROJECT_ID - type: input - - label: - text: labels.backend.gcs.service_account - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/auth/properties/GOOGLE_SERVICE_ACCOUNT_JSON_KEY - type: input - if: authEnabled - label: - text: labels.kubestash.storageSecret.label - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/auth - show_label: true - type: single-step-form - if: providerType|gcs - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs - type: single-step-form - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend - type: single-step-form - - elements: - - if: returnFalse - label: - text: labels.kubestash.storageSecret - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/storageSecret/properties/create - type: switch - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/storageSecret - type: single-step-form - - label: - text: labels.kubestash.encryptionSecret - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/encryptionSecret - type: input - - label: - text: labels.kubestash.retentionPolicy - options: - - text: Keep 1 week - value: keep-1wk - - text: Keep 1 Month - value: keep-1mo - - text: Keep 3 Month - value: keep-3mo - - text: Keep 1 Year - value: keep-1yr - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/retentionPolicy - type: select - - label: - text: labels.kubestash.schedule - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/schedule - type: input - if: presetType|kubestash - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash - type: single-step-form - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values - type: single-step-form - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec - type: single-step-form - if: isStashPreset - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets - type: single-step-form - type: single-step-form - type: single-step-form - type: single-step-form - id: opscenter-backup - title: steps.0.label -type: multi-step-form + - type: input + label: Access Key ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth/properties/AWS_ACCESS_KEY_ID + - type: input + label: Secret Access Key + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth/properties/AWS_SECRET_ACCESS_KEY + - type: input + label: CA Cert Data + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/s3/properties/auth/properties/CA_CERT_DATA + - type: block-layout + if: + name: providerType|azure + type: function + elements: + - type: input + label: Container + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/pro perties/azure/properties/spec/properties/container + - type: input + label: Max Connections + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/spec/properties/maxConnections + - type: input + label: Prefix + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/spec/properties/prefix + - type: switch + label: Enable Storage Secret? + init: + type: func + value: setStorageSecret + schema: temp/properties/azure + watcher: + func: onAuthChange|azure + paths: + - temp/properties/azure + - type: block-layout + if: + name: authEnabled + type: function + label: Storage Secret + elements: + - type: input + label: Azure Account Name + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/auth/properties/AZURE_ACCOUNT_NAME + - type: input + label: Azure Account Key + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/azure/properties/auth/properties/AZURE_ACCOUNT_KEY + - type: block-layout + if: + name: providerType|gcs + type: function + elements: + - type: input + label: Bucket + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec/properties/bucket + - type: input + label: Max Connections + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec/properties/maxConnections + - type: input + label: Prefix + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/spec/properties/prefix + - type: switch + label: Enable Storage Secret? + init: + type: func + value: setStorageSecret + schema: temp/properties/gcs + watcher: + func: onAuthChange|gcs + paths: + - temp/properties/gcs + - type: block-layout + if: + name: authEnabled + type: function + label: Storage Secret + elements: + - type: input + label: Project ID + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/auth/properties/GOOGLE_PROJECT_ID + - type: input + label: Service Account + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/backend/properties/gcs/properties/auth/properties/GOOGLE_SERVICE_ACCOUNT_JSON_KEY + - type: input + label: Encryption Secret + customClass: mt-16 + forceRequired: true + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/encryptionSecret + - type: select + label: Retention Policy + options: + - text: Keep 1 week + value: keep-1wk + - text: Keep 1 Month + value: keep-1mo + - text: Keep 3 Month + value: keep-3mo + - text: Keep 1 Year + value: keep-1yr + validation: + type: required + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/retentionPolicy + - type: input + label: Schedule + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_stash_presets/properties/spec/properties/values/properties/kubestash/properties/schedule +type: multi-step-form \ No newline at end of file diff --git a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js index ab48c27c3a..391da035df 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js @@ -1,612 +1,588 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern -let enabledFeaturesChanged = false -const backendMap = { - azure: { - spec: { container: '', maxConnections: 0, prefix: '' }, - auth: { AZURE_ACCOUNT_KEY: '', AZURE_ACCOUNT_NAME: '' }, - }, - b2: { - spec: { bucket: '', prefix: '', maxConnections: 0 }, - auth: { B2_ACCOUNT_ID: '', B2_ACCOUNT_KEY: '' }, - }, - gcs: { - spec: { bucket: '', prefix: '', maxConnections: 0 }, - auth: { GOOGLE_PROJECT_ID: '', GOOGLE_SERVICE_ACCOUNT_JSON_KEY: '' }, - }, - s3: { - spec: { endpoint: '', bucket: '', prefix: '', region: '' }, - auth: { - AWS_ACCESS_KEY_ID: '', - AWS_SECRET_ACCESS_KEY: '', - CA_CERT_DATA: '', - }, - }, - swift: { - spec: { container: '', prefix: '' }, - auth: { - OS_AUTH_TOKEN: '', - OS_AUTH_URL: '', - OS_PASSWORD: '', - OS_PROJECT_DOMAIN_NAME: '', - OS_PROJECT_NAME: '', - OS_REGION_NAME: '', - OS_STORAGE_URL: '', - OS_TENANT_ID: '', - OS_TENANT_NAME: '', - OS_USERNAME: '', - OS_USER_DOMAIN_NAME: '', - ST_AUTH: '', - ST_KEY: '', - ST_USER: '', - }, - }, -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} + setDiscriminatorValue('/enabledFeatures', []) + setDiscriminatorValue('/isResourceLoaded', false) + let resources = {} + // ************************* common functions ******************************************** + // eslint-disable-next-line no-empty-pattern + let enabledFeaturesChanged = false + const backendMap = { + azure: { + spec: { container: '', maxConnections: 0, prefix: '' }, + auth: { AZURE_ACCOUNT_KEY: '', AZURE_ACCOUNT_NAME: '' }, + }, + b2: { + spec: { bucket: '', prefix: '', maxConnections: 0 }, + auth: { B2_ACCOUNT_ID: '', B2_ACCOUNT_KEY: '' }, + }, + gcs: { + spec: { bucket: '', prefix: '', maxConnections: 0 }, + auth: { GOOGLE_PROJECT_ID: '', GOOGLE_SERVICE_ACCOUNT_JSON_KEY: '' }, + }, + s3: { + spec: { endpoint: '', bucket: '', prefix: '', region: '' }, + auth: { + AWS_ACCESS_KEY_ID: '', + AWS_SECRET_ACCESS_KEY: '', + CA_CERT_DATA: '', + }, + }, + swift: { + spec: { container: '', prefix: '' }, + auth: { + OS_AUTH_TOKEN: '', + OS_AUTH_URL: '', + OS_PASSWORD: '', + OS_PROJECT_DOMAIN_NAME: '', + OS_PROJECT_NAME: '', + OS_REGION_NAME: '', + OS_STORAGE_URL: '', + OS_TENANT_ID: '', + OS_TENANT_NAME: '', + OS_USERNAME: '', + OS_USER_DOMAIN_NAME: '', + ST_AUTH: '', + ST_KEY: '', + ST_USER: '', + }, + }, + } -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = getValue(featureSet, path) + return value + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = getValue(feature, path) + return value + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + function isEqualToModelPathValue(path, value) { + const modelValue = getValue(model, path) + return modelValue === value + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - - // for OCM - - const getRoute = storeGet('/route') - const FeatureList = storeGet('/ocm/featureSet/') - const FeatureSet = storeGet('/route/params/featureset') - - if (getRoute.fullPath.includes('/hubs/')) { - const selectedFeatureSet = - FeatureList.result?.filter((item) => { - return item.name === FeatureSet - }) || [] - const checkedFeatures = - selectedFeatureSet[0].features.filter((item) => { - return item.installed || item.recommended - }) || [] - const checkedFeatureName = - checkedFeatures.map((item) => { - return item.name - }) || [] - checkedFeatureName.push(featureBlock) - return checkedFeatureName + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(storeGet, featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames } - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + + // for OCM + + const getRoute = storeGet('/route') + const FeatureList = storeGet('/ocm/featureSet/') + const FeatureSet = storeGet('/route/params/featureset') + + if (getRoute.fullPath.includes('/hubs/')) { + const selectedFeatureSet = + FeatureList.result?.filter((item) => { + return item.name === FeatureSet + }) || [] + const checkedFeatures = + selectedFeatureSet[0].features.filter((item) => { + return item.installed || item.recommended + }) || [] + const checkedFeatureName = + checkedFeatures.map((item) => { + return item.name + }) || [] + checkedFeatureName.push(featureBlock) + return checkedFeatureName + } - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(storeGet, featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(storeGet, featureName) || + item?.spec?.featureBlock === featureBlock + ) + } } else { return ( item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock + item?.spec?.recommended || + isFeatureRequired(storeGet, featureName) ) } - } else { - return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) - ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} - -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' - - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - - return enabledFeatureNames -} + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeatures({ storeGet }) { - // fire computed function only on modal startup - if (!enabledFeaturesChanged) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { const activeFeature = storeGet('/route/query/activeFeature') || '' - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(storeGet, featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) - } + return enabledFeatureNames + } - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + function getEnabledFeatures() { + // fire computed function only on modal startup + if (!enabledFeaturesChanged) { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' + + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] + + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + } } } } -} -function disableFeatures({ - getValue, - storeGet, - itemCtx, - discriminator, - watchDependency, - setDiscriminatorValue, -}) { - watchDependency('discriminator#/isResourceLoaded') - - // unchecking stash-presets and disabling when kubestash is unchecked - watchDependency('discriminator#/enabledFeatures') - const enabledFeatures = getValue(discriminator, '/enabledFeatures') - if (!enabledFeatures?.includes('kubestash') && itemCtx.value === 'stash-presets') { - enabledFeaturesChanged = true - const idx = enabledFeatures?.indexOf('stash-presets') - if (idx !== -1) { - enabledFeatures?.splice(idx, 1) - setDiscriminatorValue('/enabledFeatures', enabledFeatures) - // update discriminator when kubestash not found but stash-presets enabled + function disableFeatures({ itemCtx }) { + // watchDependency('discriminator#/isResourceLoaded') + + // unchecking stash-presets and disabling when kubestash is unchecked + // watchDependency('discriminator#/enabledFeatures') + const enabledFeatures = getValue(discriminator, '/enabledFeatures') + if (!enabledFeatures?.includes('kubestash') && itemCtx.value === 'stash-presets') { + enabledFeaturesChanged = true + const idx = enabledFeatures?.indexOf('stash-presets') + if (idx !== -1) { + enabledFeatures?.splice(idx, 1) + setDiscriminatorValue('/enabledFeatures', enabledFeatures) + // update discriminator when kubestash not found but stash-presets enabled + } + return true } - return true - } - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails(storeGet) + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (requiredFeatures.includes(featureName)) return true - else return false -} - -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} - -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (requiredFeatures.includes(featureName)) return true + else return false + } - const allFeatures = storeGet('/cluster/features/result') || [] + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + const allFeatures = storeGet('/cluster/features/result') || [] - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) + + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') + const targetNamespace = getFeaturePropertyValue( + storeGet, + featureName, + getValue, + '/spec/chart/namespace', + ) + const sourceRef = getFeaturePropertyValue( + storeGet, + featureName, + getValue, + '/spec/chart/sourceRef', + ) + const version = getFeaturePropertyValue( + storeGet, + featureName, + getValue, + '/spec/chart/version', + ) - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) + }) + } + + function returnFalse() { + return false + } + + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') + + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const clusterset = storeGet('route/params/clusterset') + const spoke = storeGet('/route/params/spoke') + + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = + `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + + (clusterset ? `&clusterset=${clusterset}` : '') + if (spoke) + url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) } - }) -} -let resources = {} + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) -function returnFalse() { - return false -} + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) + } + }) -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const clusterset = storeGet('route/params/clusterset') - const spoke = storeGet('/route/params/spoke') - - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = - `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + - (clusterset ? `&clusterset=${clusterset}` : '') - if (spoke) - url = `/clusters/${owner}/${spoke}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} - - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + setDiscriminatorValue('/isResourceLoaded', true) + } + + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, } }) + + return options || [] } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } + + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() } - }) + } - setDiscriminatorValue('/isResourceLoaded', true) -} + function isStashPreset() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (enabledFeatures?.includes('stash-presets') && enabledFeatures?.includes('kubestash')) { + setTool() + return true + } else { + commit('wizard/model$update', { + path: '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', + value: '', + force: true, + }) + return false + } + } -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, + function presetType(value) { + const presetType = getValue( + model, + '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', + ) + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (!enabledFeatures?.includes(value)) { + return false } - }) + if (presetType?.toLowerCase() === value) return true + } - return options || [] -} + function providerType(value) { + const presetType = getValue( + model, + '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', + )?.toLowerCase() -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + const provider = getValue( + model, + `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/${presetType}/backend/provider`, + ) + return provider === value + } + + function authEnabled() { + const presetType = getValue( + model, + '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', + )?.toLowerCase() + + const isEnabled = getValue( + model, + `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/${presetType}/storageSecret/create`, + ) + return isEnabled + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + function initPrune() { + const prune = getValue( + model, + `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/stash/retentionPolicy/prune`, + ) + return prune ? prune : false } -} -function isStashPreset({ getValue, watchDependency, discriminator, commit }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - watchDependency('discriminator#/enabledFeatures') - if (enabledFeatures?.includes('stash-presets') && enabledFeatures?.includes('kubestash')) { - return true - } else { + function setTool() { commit('wizard/model$update', { path: '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', - value: '', + value: 'KubeStash', force: true, }) - return false + return 'KubeStash' } -} -function getProviderList({ getValue, watchDependency, discriminator }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - watchDependency('discriminator#/enabledFeatures') - const filteredList = enabledFeatures.filter((item) => { - if (item === 'stash-opscenter' || item === 'stash-presets') return false - return true - }) - const finalList = filteredList.map((item) => { - if (item === 'kubestash') return 'KubeStash' - else return 'Stash' - }) - return finalList -} - -function presetType({ getValue, watchDependency, model, discriminator }, value) { - watchDependency('model#/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool') - const presetType = getValue( - model, - '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', - ) - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - if (!enabledFeatures?.includes(value)) { - return false + function setProvider() { + const provider = getValue( + model, + `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/kubestash/backend/provider`, + ) + if (provider === undefined) { + return 's3' + } + return provider } - if (presetType?.toLowerCase() === value) return true -} - -function providerType({ getValue, watchDependency, model }, value) { - const presetType = getValue( - model, - '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', - )?.toLowerCase() - watchDependency( - `model#/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/${presetType}/backend/provider`, - ) - const provider = getValue( - model, - `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/${presetType}/backend/provider`, - ) - return provider === value -} - -function authEnabled({ getValue, watchDependency, model }) { - const presetType = getValue( - model, - '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', - )?.toLowerCase() - watchDependency( - `model#/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/${presetType}/storageSecret/create`, - ) - const isEnabled = getValue( - model, - `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/${presetType}/storageSecret/create`, - ) - return isEnabled -} -function initPrune({ getValue, model }) { - const prune = getValue( - model, - `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/stash/retentionPolicy/prune`, - ) - return prune ? prune : false -} - -function setTool({ commit }) { - commit('wizard/model$update', { - path: '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/tool', - value: 'KubeStash', - force: true, - }) - return 'KubeStash' -} - -function setProvider({ getValue, model }) { - const provider = getValue( - model, - `/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/kubestash/backend/provider`, - ) - if (provider === undefined) { - return 's3' + function setStorageSecret() { + const secret = getValue( + model, + '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/kubestash/storageSecret/create', + ) + return secret } - return provider -} -function setStorageSecret({ getValue, model }) { - const secret = getValue( - model, - '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/kubestash/storageSecret/create', - ) - return secret -} + function onAuthChange(type) { + const auth = getValue(discriminator, `/${type}`) || false + commit('wizard/model$update', { + path: '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/kubestash/storageSecret/create', + value: auth, + force: true, + }) + } -function onAuthChange({ getValue, discriminator, commit }, type) { - const auth = getValue(discriminator, `/${type}`) || false - commit('wizard/model$update', { - path: '/resources/helmToolkitFluxcdIoHelmRelease_stash_presets/spec/values/kubestash/storageSecret/create', - value: auth, - force: true, - }) -} + async function fetchJsons(itemCtx) { + let ui = {} + let language = {} + let functions = {} + const { name, sourceRef, version, packageviewUrlPrefix } = itemCtx.chart -async function fetchJsons({ axios, itemCtx }) { - let ui = {} - let language = {} - let functions = {} - const { name, sourceRef, version, packageviewUrlPrefix } = itemCtx.chart + try { + ui = await axios.get( + `${packageviewUrlPrefix}/create-ui.yaml?name=${name}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${version}&format=json`, + ) + language = await axios.get( + `${packageviewUrlPrefix}/language.yaml?name=${name}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${version}&format=json`, + ) + const functionString = await axios.get( + `${packageviewUrlPrefix}/functions.js?name=${name}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${version}`, + ) + // declare evaluate the functionString to get the functions Object + const evalFunc = new Function(functionString.data || '') + functions = evalFunc() + } catch (e) { + console.log(e) + } - try { - ui = await axios.get( - `${packageviewUrlPrefix}/create-ui.yaml?name=${name}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${version}&format=json`, - ) - language = await axios.get( - `${packageviewUrlPrefix}/language.yaml?name=${name}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${version}&format=json`, - ) - const functionString = await axios.get( - `${packageviewUrlPrefix}/functions.js?name=${name}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${version}`, - ) - // declare evaluate the functionString to get the functions Object - const evalFunc = new Function(functionString.data || '') - functions = evalFunc() - } catch (e) { - console.log(e) + return { + ui: ui.data || {}, + language: language.data || {}, + functions, + } } return { - ui: ui.data || {}, - language: language.data || {}, - functions, + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + isStashPreset, + presetType, + providerType, + authEnabled, + initPrune, + fetchJsons, + setTool, + setProvider, + setStorageSecret, + onAuthChange, } } - -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, - isStashPreset, - getProviderList, - presetType, - providerType, - authEnabled, - initPrune, - fetchJsons, - setTool, - setProvider, - setStorageSecret, - onAuthChange, -} From 107d454af9de2da9ece8d6860ac54b9569590b21 Mon Sep 17 00:00:00 2001 From: "Md. Samiul Haque" Date: Thu, 2 Apr 2026 11:06:59 +0600 Subject: [PATCH 10/11] ocm-spoke (#998) * ocm-spoke Signed-off-by: samiul * fixes Signed-off-by: Samiul * fixes Signed-off-by: Samiul --------- Signed-off-by: samiul Signed-off-by: Samiul --- .../ui/create-ui.yaml | 158 ++-- .../ui/functions.js | 718 +++++++++--------- .../ui/functions.js | 2 - .../ui/create-ui.yaml | 2 +- 4 files changed, 430 insertions(+), 450 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml index f8683ca362..34e4cc17c5 100644 --- a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml @@ -1,88 +1,74 @@ -steps: -- form: - discriminator: - isResourceLoaded: - default: false - type: boolean +step: +- loader: setReleaseNameAndNamespaceAndInitializeValues + type: single-step-form + id: opscenter-datastore + elements: + - type: checkbox + schema: temp/properties/enabledFeatures + label: '' + loader: fetchFeatureSetOptions + init: + type: func + value: getEnabledFeatures + watcher: + func: onEnabledFeaturesChange + paths: + - temp/properties/enabledFeatures + - type: info + label: 'Note: Enabling a feature auto enables any prerequisite features' + customClass: mt-24 + watcher: + func: checkIsResourceLoaded + paths: + - temp/properties/isResourceLoaded + - type: block-layout + if: + name: checkSpokeComponent + type: function elements: - - computed: setReleaseNameAndNamespaceAndInitializeValues - if: returnFalse - type: input - - discriminator: - enabledFeatures: - type: array - elements: - - computed: getFeatureSetDescription - customClass: mb-20 - label: - isSubsection: true - type: label-element - - computed: getEnabledFeatures - fetch: fetchFeatureSetOptions - hasDescription: true - individualItemDisabilityCheck: disableFeatures - onChange: onEnabledFeaturesChange - schema: - $ref: discriminator#/properties/enabledFeatures - type: checkbox - - computed: checkIsResourceLoaded - if: hideThisElement - type: input - - alertInfo: - show: true - type: info - label: - text: 'Note: Enabling a feature auto enables any prerequisite features' - type: label-element - - discriminator: - hubName: - type: string - elements: - - label: - text: labels.spoke.hubInfo - type: label-element - - fetch: getHubList - label: - text: labels.selectHub - onChange: onHubChange - required: true - schema: - $ref: discriminator#/properties/hubName - type: select - - disabled: true - if: isHubSelected - label: - text: labels.spoke.apiServer - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/properties/spec/properties/values/properties/hub/properties/apiServer - type: input - - disabled: true - if: isHubSelected - label: - text: labels.spoke.token - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/properties/spec/properties/values/properties/hub/properties/token - type: input - - label: - text: labels.spoke.clusterInfo - type: label-element - - computed: getClusterName - description: - text: 'Cluster Name Must not Be Same As any Managed Cluster ' - label: - text: labels.spoke.cluster - required: true - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/properties/spec/properties/values/properties/clusterMetadata/properties/name - type: input - if: checkSpokeComponent - schema: - $ref: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke - type: single-step-form - type: single-step-form - type: single-step-form - id: opscenter-core - title: steps.0.label + - type: label-element + label: Hub Information + - type: select + label: Select Hub + loader: getHubList + schema: temp/properties/hubName + validation: + type: required + - type: input + loader: + name: getHubInfo|apiServer + watchPaths: + - temp/properties/hubName + label: Api Server + disable: true + if: + name: isHubSelected + type: function + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/properties/spec/properties/values/properties/hub/properties/apiServer + validation: + type: required + - type: input + loader: + name: getHubInfo|apiServer + watchPaths: + - temp/properties/hubName + label: Token + disable: true + if: + name: isHubSelected + type: function + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/properties/spec/properties/values/properties/hub/properties/token + validation: + type: required + - type: label-element + label: Spoke Information + - type: input + label: Cluster Name + description: 'Cluster Name Must not Be Same As any Managed Cluster ' + init: + type: func + value: getClusterName + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/properties/spec/properties/values/properties/clusterMetadata/properties/name + validation: + type: required type: multi-step-form diff --git a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js index 67c74727e7..786355776d 100644 --- a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js @@ -1,426 +1,422 @@ -// ************************* common functions ******************************************** -// eslint-disable-next-line no-empty-pattern - -// get specific feature details -function getFeatureSetDetails(storeGet) { - const featureSets = storeGet('/cluster/featureSets/result') || [] - const featureSetName = storeGet('/route/params/featureset') || '' - const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) - return featureSet -} +const { axios, store, useOperator } = window.vueHelpers || {} -// get specific attribute's value of a feature -function getFeatureSetPropertyValue(storeGet, getValue, path) { - const featureSet = getFeatureSetDetails(storeGet) - const value = getValue(featureSet, path) - return value -} +export const useFunc = (model) => { + const { getValue, setDiscriminatorValue, commit, storeGet, discriminator } = useOperator( + model, + store.state, + ) -function getFeatureSetDescription({ storeGet, getValue }) { - const description = getFeatureSetPropertyValue(storeGet, getValue, '/spec/description') - return description -} + // get specific feature details + function getFeatureSetDetails() { + const featureSets = storeGet('/cluster/featureSets/result') || [] + const featureSetName = storeGet('/route/params/featureset') || '' + const featureSet = featureSets.find((item) => item?.metadata?.name === featureSetName) + return featureSet + } -// get specific feature details -function getFeatureDetails(storeGet, name) { - const features = storeGet('/cluster/features/result') || [] - const feature = features.find((item) => item?.metadata?.name === name) - return feature -} + // get specific attribute's value of a feature + function getFeatureSetPropertyValue(path) { + const featureSet = getFeatureSetDetails() + const value = getValue(featureSet, path) + return value + } -// get specific attribute's value of a feature -function getFeaturePropertyValue(storeGet, name, getValue, path) { - const feature = getFeatureDetails(storeGet, name) - const value = getValue(feature, path) - return value -} + function getFeatureSetDescription() { + const description = getFeatureSetPropertyValue('/spec/description') + return description + } -function isEqualToModelPathValue({ model, getValue, watchDependency }, path, value) { - watchDependency(`model#${path}`) + // get specific feature details + function getFeatureDetails(name) { + const features = storeGet('/cluster/features/result') || [] + const feature = features.find((item) => item?.metadata?.name === name) + return feature + } - const modelValue = getValue(model, path) - return modelValue === value -} + // get specific attribute's value of a feature + function getFeaturePropertyValue(name, path) { + const feature = getFeatureDetails(name) + const value = getValue(feature, path) + return value + } -function isFeatureRequired(storeGet, featureName) { - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - const isRequired = requiredFeatures.includes(featureName) - return isRequired -} + function isEqualToModelPathValue(path, value) { + const modelValue = getValue(model, path) + return modelValue === value + } -function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - const featureBlock = storeGet('/route/query/activeBlock') || '' - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + function isFeatureRequired(featureName) { + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const isRequired = requiredFeatures.includes(featureName) + return isRequired + } -function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel, storeGet) { - // filter only (enabled + required + feature block feature) - const featureBlock = storeGet('/route/query/activeBlock') || '' - const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { - return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended - }) - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - - if (isBlockLevel) { - if (isRecommendedFeatureAvailable) { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) - ) - } else { - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.featureBlock === featureBlock - ) - } - } else { + function getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, isBlockLevel) { + const featureBlock = storeGet('/route/query/activeBlock') || '' + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name return ( - item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(storeGet, featureName) + item?.status?.enabled || + isFeatureRequired(storeGet, featureName) || + (isBlockLevel && item?.spec?.featureBlock === featureBlock && item?.spec?.recommended) ) - } - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] - return enabledFeatureNames -} + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } -function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) { - const activeFeature = storeGet('/route/query/activeFeature') || '' + function getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, isBlockLevel) { + // filter only (enabled + required + feature block feature) + const featureBlock = storeGet('/route/query/activeBlock') || '' + const isRecommendedFeatureAvailable = allFeatureSetFeature.some((item) => { + return item?.spec?.featureBlock === featureBlock && item?.spec?.recommended + }) + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + + if (isBlockLevel) { + if (isRecommendedFeatureAvailable) { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + (item?.spec?.featureBlock === featureBlock && item?.spec?.recommended === true) + ) + } else { + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.featureBlock === featureBlock + ) + } + } else { + return item?.status?.enabled || item?.spec?.recommended || isFeatureRequired(featureName) + } + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + return enabledFeatureNames + } - const enabledFeatures = allFeatureSetFeature.filter((item) => { - const featureName = item?.metadata?.name - return ( - item?.status?.enabled || - isFeatureRequired(storeGet, featureName) || - item?.spec?.recommended || - featureName === activeFeature - ) - }) - const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] + function getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) { + const activeFeature = storeGet('/route/query/activeFeature') || '' - return enabledFeatureNames -} + const enabledFeatures = allFeatureSetFeature.filter((item) => { + const featureName = item?.metadata?.name + return ( + item?.status?.enabled || + isFeatureRequired(featureName) || + item?.spec?.recommended || + featureName === activeFeature + ) + }) + const enabledFeatureNames = enabledFeatures.map((item) => item?.metadata?.name) || [] -function getEnabledFeatures({ storeGet }) { - const allFeatures = storeGet('/cluster/features/result') || [] - const featureSet = storeGet('/route/params/featureset') || [] - const featureBlock = storeGet('/route/query/activeBlock') || '' - const configureMode = storeGet('/route/query/mode') || '' - const activeFeature = storeGet('/route/query/activeFeature') || '' + return enabledFeatureNames + } - const allFeatureSetFeature = - allFeatures.filter((item) => { - return item?.spec?.featureSet === featureSet - }) || [] + function getEnabledFeatures() { + const allFeatures = storeGet('/cluster/features/result') || [] + const featureSet = storeGet('/route/params/featureset') || [] + const featureBlock = storeGet('/route/query/activeBlock') || '' + const configureMode = storeGet('/route/query/mode') || '' + const activeFeature = storeGet('/route/query/activeFeature') || '' - if (activeFeature) { - return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature, storeGet) - } + const allFeatureSetFeature = + allFeatures.filter((item) => { + return item?.spec?.featureSet === featureSet + }) || [] - if (featureBlock) { - //feature block level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true, storeGet) - } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true, storeGet) + if (activeFeature) { + return getEnabledFeaturesFromActiveFeature(allFeatureSetFeature) } - } else { - // feature set level - if (configureMode) { - // configure btn - return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false, storeGet) + + if (featureBlock) { + //feature block level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, true) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, true) + } } else { - // enable btn - return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false, storeGet) + // feature set level + if (configureMode) { + // configure btn + return getEnabledFeatureInConfigureBtnClick(allFeatureSetFeature, false) + } else { + // enable btn + return getEnabledFeatureInEnableBtnClick(allFeatureSetFeature, false) + } } } -} - -function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDependency }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (!isResourceLoaded) return true + function disableFeatures(itemCtx) { + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (!isResourceLoaded) return true - const featureName = itemCtx.value - const featureSet = getFeatureSetDetails(storeGet) - const requiredFeatures = featureSet?.spec?.requiredFeatures || [] + const featureName = itemCtx.value + const featureSet = getFeatureSetDetails() + const requiredFeatures = featureSet?.spec?.requiredFeatures || [] - if (requiredFeatures.includes(featureName)) return true - else return false -} - -function getResourceValuePathFromFeature(feature) { - const featureName = feature?.metadata?.name || '' - const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') - const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` - return resourceValuePath -} + if (requiredFeatures.includes(featureName)) return true + else return false + } -function onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + function getResourceValuePathFromFeature(feature) { + const featureName = feature?.metadata?.name || '' + const underscoredFeatureName = featureName.toLowerCase().replaceAll('-', '_') + const resourceValuePath = `helmToolkitFluxcdIoHelmRelease_${underscoredFeatureName}` + return resourceValuePath + } - const allFeatures = storeGet('/cluster/features/result') || [] + function onEnabledFeaturesChange() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - allFeatures.forEach((item) => { - const featureName = item?.metadata?.name || '' - const resourceValuePath = getResourceValuePathFromFeature(item) + const allFeatures = storeGet('/cluster/features/result') || [] - if (enabledFeatures.includes(featureName)) { - const featureSet = storeGet('/route/params/featureset') || '' - const chart = getFeaturePropertyValue(storeGet, featureName, getValue, '/spec/chart/name') - const targetNamespace = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/namespace', - ) - const sourceRef = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/sourceRef', - ) - const version = getFeaturePropertyValue( - storeGet, - featureName, - getValue, - '/spec/chart/version', - ) + allFeatures.forEach((item) => { + const featureName = item?.metadata?.name || '' + const resourceValuePath = getResourceValuePathFromFeature(item) - const isEnabled = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/enabled') - const isManaged = getFeaturePropertyValue(storeGet, featureName, getValue, '/status/managed') + if (enabledFeatures.includes(featureName)) { + const featureSet = storeGet('/route/params/featureset') || '' + const chart = getFeaturePropertyValue(featureName, '/spec/chart/name') + const targetNamespace = getFeaturePropertyValue( + storeGet, + featureName, + getValue, + '/spec/chart/namespace', + ) + const sourceRef = getFeaturePropertyValue( + storeGet, + featureName, + getValue, + '/spec/chart/sourceRef', + ) + const version = getFeaturePropertyValue( + storeGet, + featureName, + getValue, + '/spec/chart/version', + ) - if (isEnabled && !isManaged) { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } else { - commit('wizard/model$update', { - path: `/resources/${resourceValuePath}`, - value: { - ...resources?.[resourceValuePath], - metadata: { - ...resources?.[resourceValuePath]?.metadata, - labels: { - ...resources?.[resourceValuePath]?.metadata?.labels, - 'app.kubernetes.io/component': featureName, - 'app.kubernetes.io/part-of': featureSet, + const isEnabled = getFeaturePropertyValue(featureName, '/status/enabled') + const isManaged = getFeaturePropertyValue(featureName, '/status/managed') + + if (isEnabled && !isManaged) { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) + } else { + commit('wizard/model$update', { + path: `/resources/${resourceValuePath}`, + value: { + ...resources?.[resourceValuePath], + metadata: { + ...resources?.[resourceValuePath]?.metadata, + labels: { + ...resources?.[resourceValuePath]?.metadata?.labels, + 'app.kubernetes.io/component': featureName, + 'app.kubernetes.io/part-of': featureSet, + }, }, - }, - spec: { - ...resources?.[resourceValuePath]?.spec, - chart: { - spec: { - chart, - sourceRef, - version, + spec: { + ...resources?.[resourceValuePath]?.spec, + chart: { + spec: { + chart, + sourceRef, + version, + }, }, + targetNamespace, }, - targetNamespace, }, - }, - force: true, - }) + force: true, + }) + } + } else { + commit('wizard/model$delete', `/resources/${resourceValuePath}`) } - } else { - commit('wizard/model$delete', `/resources/${resourceValuePath}`) - } - }) -} + }) + } -let resources = {} + let resources = {} -function returnFalse() { - return false -} + function returnFalse() { + return false + } -async function setReleaseNameAndNamespaceAndInitializeValues({ - commit, - storeGet, - model, - getValue, - axios, - setDiscriminatorValue, -}) { - const modelResources = getValue(model, '/resources') - resources = { ...modelResources } - - const isFeatureSetInstalled = getFeatureSetPropertyValue(storeGet, getValue, '/status/enabled') - - if (isFeatureSetInstalled) { - // get resources default values when featureset is installed - const owner = storeGet('/route/params/user') - const cluster = storeGet('/route/params/cluster') - const spoke = storeGet('/route/params/spoke') + async function setReleaseNameAndNamespaceAndInitializeValues() { + const modelResources = getValue(model, '/resources') + resources = { ...modelResources } + + const isFeatureSetInstalled = getFeatureSetPropertyValue('/status/enabled') - const { - name: chartName, - sourceRef, - version: chartVersion, - } = getFeatureSetPropertyValue(storeGet, getValue, '/spec/chart') - let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + if (isFeatureSetInstalled) { + // get resources default values when featureset is installed + const owner = storeGet('/route/params/user') + const cluster = storeGet('/route/params/cluster') + const spoke = storeGet('/route/params/spoke') - if (spoke) - url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` + const { + name: chartName, + sourceRef, + version: chartVersion, + } = getFeatureSetPropertyValue('/spec/chart') + let url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - const { data } = await axios.get(url) - const { resources: resourcesDefaultValues } = data || {} + if (spoke) + url = `/clusters/${owner}/${cluster}/helm/packageview/values?name=${chartName}&sourceApiGroup=${sourceRef.apiGroup}&sourceKind=${sourceRef.kind}&sourceNamespace=${sourceRef.namespace}&sourceName=${sourceRef.name}&version=${chartVersion}&format=json` - Object.keys(resourcesDefaultValues || {}).forEach((key) => { - if (!resources[key]) { - resources[key] = resourcesDefaultValues[key] + const { data } = await axios.get(url) + const { resources: resourcesDefaultValues } = data || {} + + Object.keys(resourcesDefaultValues || {}).forEach((key) => { + if (!resources[key]) { + resources[key] = resourcesDefaultValues[key] + } + }) + } + const featureSet = storeGet('/route/params/featureset') + commit('wizard/model$update', { + path: '/metadata/release', + value: { + name: featureSet, + namespace: 'kubeops', + }, + force: true, + }) + + // delete extra values from model if the feature does not exist + const allFeatures = storeGet('/cluster/features/result') || [] + const allFeatureResourceValuePathNames = allFeatures.map((feature) => + getResourceValuePathFromFeature(feature), + ) + Object.keys(modelResources).forEach((modelResourcePath) => { + if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { + // model path does not exist in feature values + // remove the model path + commit('wizard/model$delete', `/resources/${modelResourcePath}`) } }) + + setDiscriminatorValue('/isResourceLoaded', true) } - const featureSet = storeGet('/route/params/featureset') - commit('wizard/model$update', { - path: '/metadata/release', - value: { - name: featureSet, - namespace: 'kubeops', - }, - force: true, - }) - - // delete extra values from model if the feature does not exist - const allFeatures = storeGet('/cluster/features/result') || [] - const allFeatureResourceValuePathNames = allFeatures.map((feature) => - getResourceValuePathFromFeature(feature), - ) - Object.keys(modelResources).forEach((modelResourcePath) => { - if (!allFeatureResourceValuePathNames.includes(modelResourcePath)) { - // model path does not exist in feature values - // remove the model path - commit('wizard/model$delete', `/resources/${modelResourcePath}`) - } - }) - setDiscriminatorValue('/isResourceLoaded', true) -} + function fetchFeatureSetOptions() { + const features = storeGet('/cluster/features/result') || [] + const featureSetName = storeGet('/route/params/featureset') + const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) + const options = filteredFeatures.map((item) => { + const { spec, metadata } = item || {} + const { title, description, required } = spec || {} + const { name } = metadata || {} + return { + text: title, + value: name, + description: description, + statusTag: { + text: required ? 'Required' : '', + }, + } + }) -function fetchFeatureSetOptions({ storeGet }) { - const features = storeGet('/cluster/features/result') || [] - const featureSetName = storeGet('/route/params/featureset') - const filteredFeatures = features.filter((item) => item?.spec?.featureSet === featureSetName) - const options = filteredFeatures.map((item) => { - const { spec, metadata } = item || {} - const { title, description, required } = spec || {} - const { name } = metadata || {} - return { - text: title, - value: name, - description: description, - statusTag: { - text: required ? 'Required' : '', - }, - } - }) + return options || [] + } - return options || [] -} + // this element is is used only to catch discriminator value + // It is not used in create-ui to get or store value + function hideThisElement() { + return false + } -// this element is is used only to catch discriminator value -// It is not used in create-ui to get or store value -function hideThisElement() { - return false -} + // this computed's main purpose is to watch isResourceLoaded flag + // and fire the onEnabledFeatureChange function when it's true + function checkIsResourceLoaded() { + const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') + if (isResourceLoaded) { + onEnabledFeaturesChange() + } + } -// this computed's main purpose is to watch isResourceLoaded flag -// and fire the onEnabledFeatureChange function when it's true -function checkIsResourceLoaded({ commit, storeGet, watchDependency, getValue, discriminator }) { - watchDependency('discriminator#/isResourceLoaded') - const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') - if (isResourceLoaded) { - onEnabledFeaturesChange({ discriminator, getValue, commit, storeGet }) + function checkSpokeComponent() { + const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] + if (enabledFeatures.includes('cluster-manager-spoke')) return true + else return false } -} -function checkSpokeComponent({ watchDependency, getValue, discriminator }) { - const enabledFeatures = getValue(discriminator, '/enabledFeatures') || [] - watchDependency('discriminator#/enabledFeatures') - if (enabledFeatures.includes('cluster-manager-spoke')) return true - else return false -} + let hubData = [] -let hubData = [] + async function getHubList() { + const owner = storeGet('/route/params/user') + const resp = await axios.get(`/clustersv2/${owner}/hub-info`) -async function getHubList({ axios, storeGet }) { - const owner = storeGet('/route/params/user') - const resp = await axios.get(`/clustersv2/${owner}/hub-info`) + hubData = [{ name: 'yo', apiServer: 'https://api-server-url', token: 'token-value' }] + console.log(hubData) - hubData = Object.entries(resp.data).map(([name, info]) => ({ - name, - apiServer: info.apiServer, - token: info.token, - })) - return hubData.map((item) => item.name) -} + return hubData.map((item) => item.name) + } -function onHubChange({ commit, getValue, discriminator }) { - const hubName = getValue(discriminator, '/hubName') + function onHubChange() { + const hubName = getValue(discriminator, '/hubName') + console.log(hubName) - hubData.forEach((item) => { - if (item.name === hubName) { - commit('wizard/model$update', { - path: '/resources/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/spec/values/hub/apiServer', - value: item.apiServer, - force: true, - }) + hubData.forEach((item) => { + if (item.name === hubName) { + commit('wizard/model$update', { + path: '/resources/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/spec/values/hub/apiServer', + value: item.apiServer, + force: true, + }) - commit('wizard/model$update', { - path: '/resources/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/spec/values/hub/token', - value: item.token, - force: true, - }) - } - }) -} + commit('wizard/model$update', { + path: '/resources/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/spec/values/hub/token', + value: item.token, + force: true, + }) + } + }) + } -function isHubSelected({ getValue, discriminator, watchDependency }) { - watchDependency( - 'model#/resources/helmToolkitFluxcdIoHelmRelease_cluster_manager_spoke/spec/values/hub/token', - ) - const hubName = getValue(discriminator, '/hubName') + function getHubInfo(type) { + const hubName = getValue(discriminator, '/hubName') + const hubInfo = hubData.find((item) => item.name === hubName) || {} + if (type === 'apiServer') return hubInfo.apiServer || '' + if (type === 'token') return hubInfo.token || '' + return '' + } + + function isHubSelected() { + const hubName = getValue(discriminator, '/hubName') - if (hubName !== undefined && hubName !== '') { - return true + if (hubName !== undefined && hubName !== '') { + return true + } + return false } - return false -} -function getClusterName({ storeGet }) { - return storeGet('/route/params/cluster') -} + function getClusterName() { + return storeGet('/route/params/cluster') + } -return { - hideThisElement, - checkIsResourceLoaded, - getFeatureSetDetails, - getFeatureSetPropertyValue, - getFeatureSetDescription, - isEqualToModelPathValue, - getEnabledFeatures, - disableFeatures, - onEnabledFeaturesChange, - returnFalse, - setReleaseNameAndNamespaceAndInitializeValues, - fetchFeatureSetOptions, - checkSpokeComponent, - getHubList, - onHubChange, - isHubSelected, - getClusterName, + return { + hideThisElement, + checkIsResourceLoaded, + getFeatureSetDetails, + getFeatureSetPropertyValue, + getFeatureSetDescription, + isEqualToModelPathValue, + getEnabledFeatures, + disableFeatures, + onEnabledFeaturesChange, + returnFalse, + setReleaseNameAndNamespaceAndInitializeValues, + fetchFeatureSetOptions, + checkSpokeComponent, + getHubList, + onHubChange, + isHubSelected, + getClusterName, + getHubInfo, + } } diff --git a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js index 391da035df..68c1a8551a 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js @@ -9,8 +9,6 @@ export const useFunc = (model) => { setDiscriminatorValue('/enabledFeatures', []) setDiscriminatorValue('/isResourceLoaded', false) let resources = {} - // ************************* common functions ******************************************** - // eslint-disable-next-line no-empty-pattern let enabledFeaturesChanged = false const backendMap = { azure: { diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml index 3d8e459df1..d9fcfed2c4 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml @@ -165,7 +165,7 @@ step: - type: input label: AWS Region forceRequired: true - schema: schema#/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_REGION + schema: schema/properties/resources/properties/helmToolkitFluxcdIoHelmRelease_service_gateway_presets/properties/spec/properties/values/properties/infra/properties/dns/properties/auth/properties/route53/properties/AWS_REGION - type: input label: AWS Secret Access Key forceRequired: true From 85c9d3f8f0a637a1f184d1af93853c2678274709 Mon Sep 17 00:00:00 2001 From: Samiul Date: Fri, 3 Apr 2026 18:28:35 +0600 Subject: [PATCH 11/11] add individual disability Signed-off-by: Samiul --- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 2 + .../ui/functions.js | 16 ++- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- .../ui/create-ui.yaml | 1 + .../ui/functions.js | 2 +- schemas/ui-schema.json | 99 ++++++++++++++++++- 40 files changed, 151 insertions(+), 22 deletions(-) diff --git a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml index c5dd8bf80f..a9cd4d2520 100644 --- a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-capa-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml index 210a6eadef..c99ba2d5c8 100644 --- a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-capg-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml index f261b6bd17..6edcc17de7 100644 --- a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-capz-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml index 87af9ac052..9a94b96b4b 100644 --- a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-capi-core-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml index de02cc0a9d..48f1e5db7a 100644 --- a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-crossplane-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml index b64bf58b16..ac041be486 100644 --- a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-ocm-hub-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml index 34e4cc17c5..eb3f679ef7 100644 --- a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js index 786355776d..aed16512d0 100644 --- a/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-ocm-spoke-editor/ui/functions.js @@ -155,7 +155,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml index db0bf99305..196d0ebce8 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js index 68c1a8551a..0dc07f8302 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-backup-editor/ui/functions.js @@ -248,7 +248,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails(storeGet) const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml index 87af9ac052..83a418e1b1 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/create-ui.yaml @@ -7,6 +7,8 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js index f9e7d3455c..4053b87228 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-core-editor/ui/functions.js @@ -103,6 +103,7 @@ export const useFunc = (model) => { checkedFeatures.map((item) => { return item.name }) || [] + checkedFeatureName.push(featureBlock) return checkedFeatureName } @@ -162,6 +163,15 @@ export const useFunc = (model) => { // extreme special case for OCM featureSet if (featureSet === 'opscenter-core' && getRoute?.fullPath?.includes('/hubs/')) { + if (featureBlock === 'aceshifter') { + return [ + 'aceshifter', + 'flux2', + 'kube-ui-server', + 'license-proxyserver', + 'opscenter-features', + ] + } return ['flux2', 'kube-ui-server', 'license-proxyserver', 'opscenter-features'] } @@ -195,16 +205,18 @@ export const useFunc = (model) => { } } - function disableFeatures() { + function disableFeatures(value) { // watchDependency('discriminator#/isResourceLoaded') const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value + const getRoute = storeGet('/route') let featureSet = {} let requiredFeatures = [] + if (getRoute.fullPath.includes('/hubs/')) { featureSet = getFeatureSetDetailsOcm() requiredFeatures = featureSet?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml index b26c8e2024..bf55176485 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-cost-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml index a946952b1f..bf4179f062 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js index cc462bab12..414ccc8182 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-datastore-editor/ui/functions.js @@ -188,7 +188,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-monitoring-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-monitoring-editor/ui/functions.js index 6a855141fd..4eff62282e 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-monitoring-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-monitoring-editor/ui/functions.js @@ -156,7 +156,7 @@ function disableFeatures({ getValue, storeGet, itemCtx, discriminator, watchDepe const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails(storeGet) const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml index e28d9609ae..664ca29ac2 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-networking-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml index 19cc28e3dc..02d5f0f107 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml index 8fa137f59a..f5867423ac 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-policy-management-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml index 5141aa8c7d..4078183fa5 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-secret-management-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml index 2e5c8a4160..311a5fabe7 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js index 3684fb1674..3c282dead8 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-security-editor/ui/functions.js @@ -189,7 +189,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml index 2f37670832..f49a0d430a 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-storage-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml index fedd8ea8f8..4c3c765526 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js index ed2a267831..4f1ede6820 100644 --- a/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-opscenter-tools-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml index d9fcfed2c4..b519ba3e0e 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/create-ui.yaml @@ -7,6 +7,7 @@ step: schema: temp/properties/enabledFeatures label: '' loader: fetchFeatureSetOptions + individualDisability: disableFeatures init: type: func value: getEnabledFeatures diff --git a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js index 9741bf9aea..f43eb8621d 100644 --- a/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js +++ b/charts/uik8sappscodecom-featureset-saas-core-editor/ui/functions.js @@ -195,7 +195,7 @@ export const useFunc = (model) => { const isResourceLoaded = getValue(discriminator, '/isResourceLoaded') if (!isResourceLoaded) return true - const featureName = itemCtx.value + const featureName = value const featureSet = getFeatureSetDetails() const requiredFeatures = featureSet?.spec?.requiredFeatures || [] diff --git a/schemas/ui-schema.json b/schemas/ui-schema.json index d0700c641a..e0a2176d81 100644 --- a/schemas/ui-schema.json +++ b/schemas/ui-schema.json @@ -124,6 +124,12 @@ "box": { "type": "boolean" }, + "code": { + "type": "string" + }, + "codeContent": { + "$ref": "#/definitions/CodeCard" + }, "customClass": { "type": "string" }, @@ -165,12 +171,24 @@ "fullwidth": { "type": "boolean" }, + "hasCopy": { + "type": "boolean" + }, + "hasCrossIcon": { + "type": "boolean" + }, "hasGroup": { "type": ["boolean", "string"] }, "hasIcon": { "type": "boolean" }, + "hasPrimaryOutline": { + "type": "boolean" + }, + "hasTextCopy": { + "type": "boolean" + }, "header": { "type": "string" }, @@ -186,6 +204,9 @@ "if": { "$ref": "#/definitions/IfType" }, + "individualDisability": { + "$ref": "#/definitions/LoaderType" + }, "init": { "$ref": "#/definitions/Init" }, @@ -250,7 +271,8 @@ "multi-file-editor", "time-picker", "threshold-input", - "input-compare" + "input-compare", + "code-card" ], "type": "string" }, @@ -479,6 +501,9 @@ }, { "$ref": "#/definitions/InputCompare" + }, + { + "$ref": "#/definitions/CodeCard" } ] }, @@ -570,6 +595,9 @@ "if": { "$ref": "#/definitions/IfType" }, + "individualDisability": { + "$ref": "#/definitions/LoaderType" + }, "init": { "$ref": "#/definitions/Init" }, @@ -602,6 +630,69 @@ "required": ["label", "schema", "type"], "type": "object" }, + "CodeCard": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "customClass": { + "type": "string" + }, + "description": { + "type": "string" + }, + "disable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/LoaderType" + } + ] + }, + "hasCopy": { + "type": "boolean" + }, + "hasPrimaryOutline": { + "type": "boolean" + }, + "hasTextCopy": { + "type": "boolean" + }, + "if": { + "$ref": "#/definitions/IfType" + }, + "init": { + "$ref": "#/definitions/Init" + }, + "label": { + "type": "string" + }, + "loader": { + "$ref": "#/definitions/LoaderType" + }, + "schema": { + "type": "string" + }, + "subtitle": { + "type": "string" + }, + "type": { + "const": "code-card", + "type": "string" + }, + "validation": { + "$ref": "#/definitions/Validation" + }, + "watcher": { + "$ref": "#/definitions/Watchers" + } + }, + "required": ["type"], + "type": "object" + }, "DerivedElement": { "anyOf": [ { @@ -899,6 +990,9 @@ "box": { "type": "boolean" }, + "codeContent": { + "$ref": "#/definitions/CodeCard" + }, "customClass": { "type": "string" }, @@ -915,6 +1009,9 @@ } ] }, + "hasCrossIcon": { + "type": "boolean" + }, "hasIcon": { "type": "boolean" },