Skip to content

Commit 0502f4b

Browse files
Add monitoring cluster to appscode otel stack featureset (#1024)
Signed-off-by: rafi <rafialam@appscode.com> Signed-off-by: RokibulHasan7 <mdrokibulhasan@appscode.com> Signed-off-by: rafi-ruetcse17 <rafialam6610@gmail.com> Signed-off-by: Arnob kumar saha <arnob@appscode.com> Co-authored-by: RokibulHasan7 <mdrokibulhasan@appscode.com>
1 parent 4c82906 commit 0502f4b

6 files changed

Lines changed: 264 additions & 29 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{{- with .Values.resources }}
2+
{{- with .helmToolkitFluxcdIoHelmRelease_prom_label_proxy }}
3+
{{- . | toYaml }}
4+
{{- end }}
5+
{{- end }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{{- with .Values.resources }}
2+
{{- with .helmToolkitFluxcdIoHelmRelease_tenant_operator }}
3+
{{- . | toYaml }}
4+
{{- end }}
5+
{{- end }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{{- with .Values.resources }}
2+
{{- with .helmToolkitFluxcdIoHelmRelease_thanos_operator }}
3+
{{- . | toYaml }}
4+
{{- end }}
5+
{{- end }}
Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
11
step:
2-
- elements:
3-
- individualDisability: disableFeatures
4-
init:
5-
type: func
6-
value: getEnabledFeatures
7-
label: ""
8-
loader: fetchFeatureSetOptions
9-
schema: temp/properties/enabledFeatures
10-
type: checkbox
11-
watcher:
12-
func: onEnabledFeaturesChange
13-
paths:
14-
- temp/properties/enabledFeatures
15-
- customClass: mt-24
16-
label: 'Note: Enabling a feature auto enables any prerequisite features'
17-
type: info
18-
watcher:
19-
func: checkIsResourceLoaded
20-
paths:
21-
- temp/properties/isResourceLoaded
22-
id: opscenter-monitoring
23-
loader: setReleaseNameAndNamespaceAndInitializeValues
24-
type: single-step-form
2+
- elements:
3+
- individualDisability: disableFeatures
4+
init:
5+
type: func
6+
value: getEnabledFeatures
7+
label: ''
8+
loader: fetchFeatureSetOptions
9+
schema: temp/properties/enabledFeatures
10+
type: checkbox
11+
watcher:
12+
func: onEnabledFeaturesChange
13+
paths:
14+
- temp/properties/enabledFeatures
15+
- customClass: mt-24
16+
label: 'Note: Enabling a feature auto enables any prerequisite features'
17+
type: info
18+
watcher:
19+
func: checkIsResourceLoaded
20+
paths:
21+
- temp/properties/isResourceLoaded
22+
- type: select
23+
if:
24+
name: checkIsOtelStackEnabled
25+
type: function
26+
loader: fetchMonitoringClusterOptions
27+
label: Select Monitoring Cluster
28+
schema: temp/properties/monitoringClusterName
29+
watcher:
30+
func: onMonitoringClusterChange
31+
paths:
32+
- temp/properties/monitoringClusterName
33+
validation:
34+
type: required
35+
id: opscenter-monitoring
36+
loader: setReleaseNameAndNamespaceAndInitializeValues
37+
type: single-step-form
2538
type: multi-step-form

charts/uik8sappscodecom-featureset-opscenter-observability-editor/ui/functions.js

Lines changed: 120 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const useFunc = (model) => {
88

99
setDiscriminatorValue('/enabledFeatures', [])
1010
setDiscriminatorValue('/isResourceLoaded', false)
11+
const appsCodeOtelStack = 'appscode-otel-stack'
1112
let resources = {}
1213

1314
// get specific feature details
@@ -210,12 +211,57 @@ export const useFunc = (model) => {
210211
return resourceValuePath
211212
}
212213

213-
function onEnabledFeaturesChange() {
214+
function deepMergeValues(existingValues, newValues) {
215+
if (!newValues) return existingValues
216+
if (!existingValues) return newValues
217+
218+
const merged = { ...existingValues }
219+
220+
Object.keys(newValues).forEach((key) => {
221+
if (
222+
typeof newValues[key] === 'object' &&
223+
newValues[key] !== null &&
224+
!Array.isArray(newValues[key])
225+
) {
226+
merged[key] = deepMergeValues(existingValues[key], newValues[key])
227+
} else {
228+
merged[key] = newValues[key]
229+
}
230+
})
231+
232+
return merged
233+
}
234+
235+
// fetch monitoring cluster configuration
236+
async function fetchMonitoringClusterConfig(monitoringClusterName) {
237+
if (!monitoringClusterName) {
238+
return null
239+
}
240+
241+
const getRoute = storeGet('/route')
242+
const spokeCluster = getRoute.params?.spoke
243+
const owner = storeGet('/route/params/user')
244+
const cluster = storeGet('/route/params/cluster')
245+
let url = `/telemetry/${owner}/${monitoringClusterName}/values/appscode-otel-stack`
246+
if (cluster) {
247+
if (getRoute.fullPath.includes('/hubs/') && spokeCluster) {
248+
url += `?targetClusterName=${encodeURIComponent(spokeCluster)}`
249+
} else {
250+
url += `?targetClusterName=${encodeURIComponent(cluster)}`
251+
}
252+
}
253+
const { data } = await axios.get(url)
254+
return data
255+
}
256+
257+
async function onEnabledFeaturesChange() {
214258
const enabledFeatures = getValue(discriminator, '/enabledFeatures') || []
259+
const monitoringClusterName = getValue(discriminator, '/monitoringClusterName')
260+
let monitoringClusterConfig = getValue(discriminator, '/monitoringClusterConfig')
215261

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

218-
allFeatures.forEach((item) => {
264+
for (const item of allFeatures) {
219265
const featureName = item?.metadata?.name || ''
220266
const resourceValuePath = getResourceValuePathFromFeature(item)
221267

@@ -233,6 +279,23 @@ export const useFunc = (model) => {
233279
if (isEnabled && !isManaged) {
234280
commit('wizard/model$delete', `/resources/${resourceValuePath}`)
235281
} else {
282+
// Merge existing values with otelStack data only for appscode-otel-stack feature
283+
const initialResourceValues = resources?.[resourceValuePath]?.spec?.values
284+
let mergedResourceValues = initialResourceValues
285+
286+
let finalSourceRef = sourceRef
287+
if (
288+
featureName === appsCodeOtelStack &&
289+
monitoringClusterName &&
290+
monitoringClusterConfig
291+
) {
292+
mergedResourceValues = deepMergeValues(initialResourceValues, monitoringClusterConfig)
293+
finalSourceRef = {
294+
...sourceRef,
295+
monitoringCluster: monitoringClusterName,
296+
}
297+
}
298+
236299
commit('wizard/model$update', {
237300
path: `/resources/${resourceValuePath}`,
238301
value: {
@@ -247,10 +310,11 @@ export const useFunc = (model) => {
247310
},
248311
spec: {
249312
...resources?.[resourceValuePath]?.spec,
313+
values: mergedResourceValues,
250314
chart: {
251315
spec: {
252316
chart,
253-
sourceRef,
317+
sourceRef: finalSourceRef,
254318
version,
255319
},
256320
},
@@ -263,7 +327,7 @@ export const useFunc = (model) => {
263327
} else {
264328
commit('wizard/model$delete', `/resources/${resourceValuePath}`)
265329
}
266-
})
330+
}
267331
}
268332

269333
function returnFalse() {
@@ -359,14 +423,61 @@ export const useFunc = (model) => {
359423

360424
// this computed's main purpose is to watch isResourceLoaded flag
361425
// and fire the onEnabledFeatureChange function when it's true
362-
function checkIsResourceLoaded() {
426+
async function checkIsResourceLoaded() {
363427
// watchDependency('discriminator#/isResourceLoaded')
364428
const isResourceLoaded = getValue(discriminator, '/isResourceLoaded')
365429
if (isResourceLoaded) {
366-
onEnabledFeaturesChange()
430+
await onEnabledFeaturesChange()
367431
}
368432
}
369433

434+
//this function is used to check if AppsCode OpenTelemetry Stack is enabled
435+
//it is the condition to show monitoring cluster dropdown
436+
function checkIsOtelStackEnabled() {
437+
// watchDependency('discriminator#/enabledFeatures')
438+
const enabledFeatures = getValue(discriminator, '/enabledFeatures') || []
439+
if (enabledFeatures.includes(appsCodeOtelStack)) {
440+
return true
441+
}
442+
return false
443+
}
444+
445+
//this function is used to fetch monitoring cluster options from dropdown
446+
async function fetchMonitoringClusterOptions() {
447+
const enabledFeatures = getValue(discriminator, '/enabledFeatures') || []
448+
if (!enabledFeatures.includes(appsCodeOtelStack)) {
449+
return []
450+
}
451+
452+
const getRoute = storeGet('/route')
453+
const spokeCluster = getRoute.params?.spoke
454+
const owner = storeGet('/route/params/user')
455+
const cluster = storeGet('/route/params/cluster')
456+
let url = `/telemetry/${owner}/monitoring-clusters`
457+
if (cluster) {
458+
if (getRoute.fullPath.includes('/hubs/') && spokeCluster) {
459+
url += `?targetClusterName=${encodeURIComponent(spokeCluster)}`
460+
} else {
461+
url += `?targetClusterName=${encodeURIComponent(cluster)}`
462+
}
463+
}
464+
const { data } = await axios.get(url)
465+
466+
return data || []
467+
}
468+
469+
async function onMonitoringClusterChange() {
470+
const monitoringClusterName = getValue(discriminator, '/monitoringClusterName')
471+
if (!monitoringClusterName) {
472+
return
473+
}
474+
475+
const data = await fetchMonitoringClusterConfig(monitoringClusterName)
476+
477+
setDiscriminatorValue('/monitoringClusterConfig', data)
478+
await onEnabledFeaturesChange()
479+
}
480+
370481
return {
371482
hideThisElement,
372483
checkIsResourceLoaded,
@@ -380,5 +491,8 @@ export const useFunc = (model) => {
380491
returnFalse,
381492
setReleaseNameAndNamespaceAndInitializeValues,
382493
fetchFeatureSetOptions,
494+
checkIsOtelStackEnabled,
495+
fetchMonitoringClusterOptions,
496+
onMonitoringClusterChange,
383497
}
384498
}

charts/uik8sappscodecom-featureset-opscenter-observability-editor/values.yaml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,99 @@ resources:
195195
crds: CreateReplace
196196
remediation:
197197
retries: -1
198+
helmToolkitFluxcdIoHelmRelease_prom_label_proxy: # +doc-gen:break
199+
apiVersion: helm.toolkit.fluxcd.io/v2
200+
kind: HelmRelease
201+
metadata:
202+
labels:
203+
app.kubernetes.io/component: prom-label-proxy
204+
name: prom-label-proxy
205+
namespace: kubeops
206+
spec:
207+
chart:
208+
spec:
209+
chart: prom-label-proxy
210+
sourceRef:
211+
kind: HelmRepository
212+
name: appscode-charts-oci
213+
namespace: kubeops
214+
version: v2025.4.30
215+
install:
216+
crds: CreateReplace
217+
createNamespace: true
218+
remediation:
219+
retries: -1
220+
interval: 5m
221+
releaseName: prom-label-proxy
222+
storageNamespace: monitoring
223+
targetNamespace: monitoring
224+
timeout: 30m
225+
upgrade:
226+
crds: CreateReplace
227+
remediation:
228+
retries: -1
229+
helmToolkitFluxcdIoHelmRelease_thanos_operator: # +doc-gen:break
230+
apiVersion: helm.toolkit.fluxcd.io/v2
231+
kind: HelmRelease
232+
metadata:
233+
labels:
234+
app.kubernetes.io/component: thanos-operator
235+
name: thanos-operator
236+
namespace: kubeops
237+
spec:
238+
chart:
239+
spec:
240+
chart: thanos-operator
241+
sourceRef:
242+
kind: HelmRepository
243+
name: appscode-charts-oci
244+
namespace: kubeops
245+
version: v2025.4.30
246+
install:
247+
crds: CreateReplace
248+
createNamespace: true
249+
remediation:
250+
retries: -1
251+
interval: 5m
252+
releaseName: thanos-operator
253+
storageNamespace: monitoring
254+
targetNamespace: monitoring
255+
timeout: 30m
256+
upgrade:
257+
crds: CreateReplace
258+
remediation:
259+
retries: -1
260+
helmToolkitFluxcdIoHelmRelease_tenant_operator: # +doc-gen:break
261+
apiVersion: helm.toolkit.fluxcd.io/v2
262+
kind: HelmRelease
263+
metadata:
264+
labels:
265+
app.kubernetes.io/component: tenant-operator
266+
name: tenant-operator
267+
namespace: kubeops
268+
spec:
269+
chart:
270+
spec:
271+
chart: tenant-operator
272+
sourceRef:
273+
kind: HelmRepository
274+
name: appscode-charts-oci
275+
namespace: kubeops
276+
version: v2025.4.30
277+
install:
278+
crds: CreateReplace
279+
createNamespace: true
280+
remediation:
281+
retries: -1
282+
interval: 5m
283+
releaseName: tenant-operator
284+
storageNamespace: monitoring
285+
targetNamespace: monitoring
286+
timeout: 30m
287+
upgrade:
288+
crds: CreateReplace
289+
remediation:
290+
retries: -1
198291
helmToolkitFluxcdIoHelmRelease_kube_prometheus_stack: # +doc-gen:break
199292
apiVersion: helm.toolkit.fluxcd.io/v2
200293
kind: HelmRelease

0 commit comments

Comments
 (0)