Skip to content
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{- with .Values.resources }}
{{- with .helmToolkitFluxcdIoHelmRelease_prom_label_proxy }}
{{- . | toYaml }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{- with .Values.resources }}
{{- with .helmToolkitFluxcdIoHelmRelease_tenant_operator }}
{{- . | toYaml }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{- with .Values.resources }}
{{- with .helmToolkitFluxcdIoHelmRelease_thanos_operator }}
{{- . | toYaml }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
step:
- elements:
- individualDisability: disableFeatures
init:
type: func
value: getEnabledFeatures
label: ""
loader: fetchFeatureSetOptions
schema: temp/properties/enabledFeatures
type: checkbox
watcher:
func: onEnabledFeaturesChange
paths:
- temp/properties/enabledFeatures
- customClass: mt-24
label: 'Note: Enabling a feature auto enables any prerequisite features'
type: info
watcher:
func: checkIsResourceLoaded
paths:
- temp/properties/isResourceLoaded
id: opscenter-monitoring
loader: setReleaseNameAndNamespaceAndInitializeValues
type: single-step-form
- elements:
- individualDisability: disableFeatures
init:
type: func
value: getEnabledFeatures
label: ''
loader: fetchFeatureSetOptions
schema: temp/properties/enabledFeatures
type: checkbox
watcher:
func: onEnabledFeaturesChange
paths:
- temp/properties/enabledFeatures
- customClass: mt-24
label: 'Note: Enabling a feature auto enables any prerequisite features'
type: info
watcher:
func: checkIsResourceLoaded
paths:
- temp/properties/isResourceLoaded
- type: select
if:
name: checkIsOtelStackEnabled
type: function
loader: fetchMonitoringClusterOptions
label: Select Monitoring Cluster
schema: temp/properties/monitoringClusterName
watcher:
func: onMonitoringClusterChange
paths:
- temp/properties/monitoringClusterName
validation:
type: required
id: opscenter-monitoring
loader: setReleaseNameAndNamespaceAndInitializeValues
type: single-step-form
type: multi-step-form
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const useFunc = (model) => {

setDiscriminatorValue('/enabledFeatures', [])
setDiscriminatorValue('/isResourceLoaded', false)
const appsCodeOtelStack = 'appscode-otel-stack'
let resources = {}

// get specific feature details
Expand Down Expand Up @@ -210,12 +211,57 @@ export const useFunc = (model) => {
return resourceValuePath
}

function onEnabledFeaturesChange() {
function deepMergeValues(existingValues, newValues) {
if (!newValues) return existingValues
if (!existingValues) return newValues

const merged = { ...existingValues }

Object.keys(newValues).forEach((key) => {
if (
typeof newValues[key] === 'object' &&
newValues[key] !== null &&
!Array.isArray(newValues[key])
) {
merged[key] = deepMergeValues(existingValues[key], newValues[key])
} else {
merged[key] = newValues[key]
}
})

return merged
}

// fetch monitoring cluster configuration
async function fetchMonitoringClusterConfig(monitoringClusterName) {
if (!monitoringClusterName) {
return null
}

const getRoute = storeGet('/route')
const spokeCluster = getRoute.params?.spoke
const owner = storeGet('/route/params/user')
const cluster = storeGet('/route/params/cluster')
let url = `/telemetry/${owner}/${monitoringClusterName}/values/appscode-otel-stack`
if (cluster) {
if (getRoute.fullPath.includes('/hubs/') && spokeCluster) {
url += `?targetClusterName=${encodeURIComponent(spokeCluster)}`
} else {
url += `?targetClusterName=${encodeURIComponent(cluster)}`
}
}
const { data } = await axios.get(url)
return data
}

async function onEnabledFeaturesChange() {
const enabledFeatures = getValue(discriminator, '/enabledFeatures') || []
const monitoringClusterName = getValue(discriminator, '/monitoringClusterName')
let monitoringClusterConfig = getValue(discriminator, '/monitoringClusterConfig')

const allFeatures = storeGet('/cluster/features/result') || []

allFeatures.forEach((item) => {
for (const item of allFeatures) {
const featureName = item?.metadata?.name || ''
const resourceValuePath = getResourceValuePathFromFeature(item)

Expand All @@ -233,6 +279,23 @@ export const useFunc = (model) => {
if (isEnabled && !isManaged) {
commit('wizard/model$delete', `/resources/${resourceValuePath}`)
} else {
// Merge existing values with otelStack data only for appscode-otel-stack feature
const initialResourceValues = resources?.[resourceValuePath]?.spec?.values
let mergedResourceValues = initialResourceValues

let finalSourceRef = sourceRef
if (
featureName === appsCodeOtelStack &&
monitoringClusterName &&
monitoringClusterConfig
) {
mergedResourceValues = deepMergeValues(initialResourceValues, monitoringClusterConfig)
finalSourceRef = {
...sourceRef,
monitoringCluster: monitoringClusterName,
}
}

commit('wizard/model$update', {
path: `/resources/${resourceValuePath}`,
value: {
Expand All @@ -247,10 +310,11 @@ export const useFunc = (model) => {
},
spec: {
...resources?.[resourceValuePath]?.spec,
values: mergedResourceValues,
chart: {
spec: {
chart,
sourceRef,
sourceRef: finalSourceRef,
version,
},
},
Expand All @@ -263,7 +327,7 @@ export const useFunc = (model) => {
} else {
commit('wizard/model$delete', `/resources/${resourceValuePath}`)
}
})
}
}

function returnFalse() {
Expand Down Expand Up @@ -359,14 +423,61 @@ 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() {
async function checkIsResourceLoaded() {
// watchDependency('discriminator#/isResourceLoaded')
const isResourceLoaded = getValue(discriminator, '/isResourceLoaded')
if (isResourceLoaded) {
onEnabledFeaturesChange()
await onEnabledFeaturesChange()
}
}

//this function is used to check if AppsCode OpenTelemetry Stack is enabled
//it is the condition to show monitoring cluster dropdown
function checkIsOtelStackEnabled() {
// watchDependency('discriminator#/enabledFeatures')
const enabledFeatures = getValue(discriminator, '/enabledFeatures') || []
if (enabledFeatures.includes(appsCodeOtelStack)) {
return true
}
return false
}

//this function is used to fetch monitoring cluster options from dropdown
async function fetchMonitoringClusterOptions() {
const enabledFeatures = getValue(discriminator, '/enabledFeatures') || []
if (!enabledFeatures.includes(appsCodeOtelStack)) {
return []
}

const getRoute = storeGet('/route')
const spokeCluster = getRoute.params?.spoke
const owner = storeGet('/route/params/user')
const cluster = storeGet('/route/params/cluster')
let url = `/telemetry/${owner}/monitoring-clusters`
if (cluster) {
if (getRoute.fullPath.includes('/hubs/') && spokeCluster) {
url += `?targetClusterName=${encodeURIComponent(spokeCluster)}`
} else {
url += `?targetClusterName=${encodeURIComponent(cluster)}`
}
}
const { data } = await axios.get(url)

return data || []
}

async function onMonitoringClusterChange() {
const monitoringClusterName = getValue(discriminator, '/monitoringClusterName')
if (!monitoringClusterName) {
return
}

const data = await fetchMonitoringClusterConfig(monitoringClusterName)

setDiscriminatorValue('/monitoringClusterConfig', data)
await onEnabledFeaturesChange()
}

return {
hideThisElement,
checkIsResourceLoaded,
Expand All @@ -380,5 +491,8 @@ export const useFunc = (model) => {
returnFalse,
setReleaseNameAndNamespaceAndInitializeValues,
fetchFeatureSetOptions,
checkIsOtelStackEnabled,
fetchMonitoringClusterOptions,
onMonitoringClusterChange,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,99 @@ resources:
crds: CreateReplace
remediation:
retries: -1
helmToolkitFluxcdIoHelmRelease_prom_label_proxy: # +doc-gen:break
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
labels:
app.kubernetes.io/component: prom-label-proxy
name: prom-label-proxy
namespace: kubeops
spec:
chart:
spec:
chart: prom-label-proxy
sourceRef:
kind: HelmRepository
name: appscode-charts-oci
namespace: kubeops
version: v2025.4.30
install:
crds: CreateReplace
createNamespace: true
remediation:
retries: -1
interval: 5m
releaseName: prom-label-proxy
storageNamespace: monitoring
targetNamespace: monitoring
timeout: 30m
upgrade:
crds: CreateReplace
remediation:
retries: -1
helmToolkitFluxcdIoHelmRelease_thanos_operator: # +doc-gen:break
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
labels:
app.kubernetes.io/component: thanos-operator
name: thanos-operator
namespace: kubeops
spec:
chart:
spec:
chart: thanos-operator
sourceRef:
kind: HelmRepository
name: appscode-charts-oci
namespace: kubeops
version: v2025.4.30
install:
crds: CreateReplace
createNamespace: true
remediation:
retries: -1
interval: 5m
releaseName: thanos-operator
storageNamespace: monitoring
targetNamespace: monitoring
timeout: 30m
upgrade:
crds: CreateReplace
remediation:
retries: -1
helmToolkitFluxcdIoHelmRelease_tenant_operator: # +doc-gen:break
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
labels:
app.kubernetes.io/component: tenant-operator
name: tenant-operator
namespace: kubeops
spec:
chart:
spec:
chart: tenant-operator
sourceRef:
kind: HelmRepository
name: appscode-charts-oci
namespace: kubeops
version: v2025.4.30
install:
crds: CreateReplace
createNamespace: true
remediation:
retries: -1
interval: 5m
releaseName: tenant-operator
storageNamespace: monitoring
targetNamespace: monitoring
timeout: 30m
upgrade:
crds: CreateReplace
remediation:
retries: -1
helmToolkitFluxcdIoHelmRelease_kube_prometheus_stack: # +doc-gen:break
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
Expand Down
Loading