Skip to content

Commit 35abe2d

Browse files
myasnikovdaniillexfrei
authored andcommitted
fix(dashboard, kubernetes): say which cluster addons have no enable switch
cilium, coredns and verticalPodAutoscaler carry only valuesOverride and no enabled, and the addon template keys its toggle off the presence of enabled, so all three rendered as plain groups among the toggleable addons, reading as a switch that failed to appear. That is what leads users to add <addon>.enabled: true in the YAML editor, where the schema sets no additionalProperties, so the API stores the field and echoes it back while nothing reads it. The three are not the same case, so the form must not claim they are. cilium and coredns are always installed. verticalPodAutoscaler has no switch of its own but is installed and removed together with addons.monitoringAgents.enabled, so calling it mandatory would be wrong. The fixed copy states only what holds for all three, that there is no enable switch and that an enabled field in YAML does nothing, and the per-addon reason moves into the schema description, which the form already renders and which regenerates into the README, the Go types and the ApplicationDefinition. Also types the test fixture instead of spreading it as object, which erased the props and left the file failing tsc. Fixes #3108 Assisted-by: LLM Signed-off-by: Myasnikov Daniil <[email protected]>
1 parent 242786f commit 35abe2d

7 files changed

Lines changed: 142 additions & 44 deletions

File tree

‎api/apps/v1alpha1/kubernetes/types.go‎

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/apps/kubernetes/README.md‎

Lines changed: 34 additions & 34 deletions
Large diffs are not rendered by default.

‎packages/apps/kubernetes/values.schema.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@
220220
}
221221
},
222222
"cilium": {
223-
"description": "Cilium CNI plugin.",
223+
"description": "Cilium CNI plugin. Always installed: it is the tenant cluster's CNI and has no enable switch, so this section only overrides its Helm values.",
224224
"type": "object",
225225
"default": {},
226226
"required": [
@@ -236,7 +236,7 @@
236236
}
237237
},
238238
"coredns": {
239-
"description": "CoreDNS addon.",
239+
"description": "CoreDNS addon. Always installed: it is the tenant cluster's DNS and has no enable switch, so this section only overrides its Helm values.",
240240
"type": "object",
241241
"default": {},
242242
"required": [
@@ -417,7 +417,7 @@
417417
}
418418
},
419419
"verticalPodAutoscaler": {
420-
"description": "Vertical Pod Autoscaler.",
420+
"description": "Vertical Pod Autoscaler. Has no enable switch of its own: it is installed and removed together with addons.monitoringAgents.enabled, so this section only overrides its Helm values.",
421421
"type": "object",
422422
"default": {},
423423
"required": [

‎packages/apps/kubernetes/values.yaml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,15 @@ proxmox:
184184

185185
## @typedef {struct} Addons - Cluster addons configuration.
186186
## @field {CertManagerAddon} certManager - Cert-manager addon.
187-
## @field {CiliumAddon} cilium - Cilium CNI plugin.
187+
## @field {CiliumAddon} cilium - Cilium CNI plugin. Always installed: it is the tenant cluster's CNI and has no enable switch, so this section only overrides its Helm values.
188188
## @field {GatewayAPIAddon} gatewayAPI - Gateway API addon.
189189
## @field {IngressNginxAddon} ingressNginx - Ingress-NGINX controller.
190190
## @field {GPUOperatorAddon} gpuOperator - NVIDIA GPU Operator.
191191
## @field {HAMiAddon} hami - HAMi GPU virtualization middleware.
192192
## @field {MonitoringAgentsAddon} monitoringAgents - Monitoring agents.
193-
## @field {VerticalPodAutoscalerAddon} verticalPodAutoscaler - Vertical Pod Autoscaler.
193+
## @field {VerticalPodAutoscalerAddon} verticalPodAutoscaler - Vertical Pod Autoscaler. Has no enable switch of its own: it is installed and removed together with addons.monitoringAgents.enabled, so this section only overrides its Helm values.
194194
## @field {VeleroAddon} velero - Velero backup/restore addon.
195-
## @field {CoreDNSAddon} coredns - CoreDNS addon.
195+
## @field {CoreDNSAddon} coredns - CoreDNS addon. Always installed: it is the tenant cluster's DNS and has no enable switch, so this section only overrides its Helm values.
196196
## @field {OuroborosAddon} ouroboros - Hairpin-NAT fix for ingress-nginx with PROXY-protocol.
197197

198198
## @param {Addons} addons - Cluster addons configuration.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { describe, expect, it } from "vitest"
2+
import { render, screen } from "@testing-library/react"
3+
import type { ObjectFieldTemplateProps, ObjectFieldTemplatePropertyType } from "@rjsf/utils"
4+
import { CustomObjectFieldTemplate } from "./CustomObjectFieldTemplate.tsx"
5+
6+
const prop = (name: string): ObjectFieldTemplatePropertyType => ({
7+
name,
8+
content: <div data-testid={`field-${name}`} />,
9+
disabled: false,
10+
readonly: false,
11+
hidden: false,
12+
})
13+
14+
// One cast at the fixture boundary keeps every render call below fully typed;
15+
// `registry` is a large RJSF object this template never reads.
16+
const base = {
17+
idSchema: { $id: "root_addons_cilium" },
18+
schema: {},
19+
title: "cilium",
20+
description: "Cilium CNI plugin.",
21+
formData: {},
22+
properties: [],
23+
onAddClick: () => () => {},
24+
registry: {},
25+
} as unknown as ObjectFieldTemplateProps
26+
27+
describe("addons with no enable switch", () => {
28+
it("says the switch is absent when the object carries only valuesOverride", () => {
29+
render(<CustomObjectFieldTemplate {...base} properties={[prop("valuesOverride")]} />)
30+
expect(screen.getByText(/No enable switch/)).toBeTruthy()
31+
expect(screen.queryByRole("checkbox")).toBeNull()
32+
})
33+
34+
it("warns that an enabled field in YAML does nothing", () => {
35+
render(<CustomObjectFieldTemplate {...base} properties={[prop("valuesOverride")]} />)
36+
expect(screen.getByText(/adding an enabled field in YAML has no effect/)).toBeTruthy()
37+
})
38+
39+
// The three addons in this class are not all always-on: verticalPodAutoscaler
40+
// follows addons.monitoringAgents.enabled. Only the schema description knows
41+
// which is which, so the fixed copy must not claim any of them is mandatory.
42+
it("leaves the reason to the schema description", () => {
43+
render(
44+
<CustomObjectFieldTemplate
45+
{...base}
46+
title="verticalPodAutoscaler"
47+
description="Vertical Pod Autoscaler. Has no enable switch of its own: it is installed and removed together with addons.monitoringAgents.enabled, so this section only overrides its Helm values."
48+
properties={[prop("valuesOverride")]}
49+
/>,
50+
)
51+
expect(screen.getByText(/together with addons.monitoringAgents.enabled/)).toBeTruthy()
52+
expect(screen.queryByText(/cannot be disabled/)).toBeNull()
53+
expect(screen.queryByText(/Always on/)).toBeNull()
54+
})
55+
56+
it("leaves a toggleable addon alone", () => {
57+
render(
58+
<CustomObjectFieldTemplate
59+
{...base}
60+
properties={[prop("enabled"), prop("valuesOverride")]}
61+
/>,
62+
)
63+
expect(screen.queryByText(/No enable switch/)).toBeNull()
64+
expect(screen.getByTestId("field-enabled")).toBeTruthy()
65+
})
66+
})

‎packages/system/dashboard/images/console/apps/console/src/components/CustomObjectFieldTemplate.tsx‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,38 @@ export function CustomObjectFieldTemplate<
5353
const hasOtherFields = props.properties.some((p) => p.name !== "enabled")
5454
const isAddon = hasEnabledField && hasOtherFields
5555

56+
// An addon carrying only overrides and no 'enabled' has no switch of its own:
57+
// cilium and coredns are always installed, verticalPodAutoscaler follows
58+
// monitoringAgents. Rendered as a plain group it reads as a toggleable addon
59+
// whose switch failed to appear, which is how users end up adding
60+
// `<addon>.enabled: true` in YAML — the schema sets no additionalProperties,
61+
// so the API stores that field, echoes it back, and nothing reads it. State
62+
// the absence here; the per-addon schema description says why.
63+
const hasNoToggle =
64+
!hasEnabledField &&
65+
props.properties.length > 0 &&
66+
props.properties.every((p) => p.name === "valuesOverride")
67+
68+
if (hasNoToggle) {
69+
return (
70+
<fieldset id={props.idSchema.$id} className="border border-slate-200 rounded-lg p-3 mb-3">
71+
{props.title && (
72+
<legend className="text-xs font-semibold text-slate-700 px-1">{props.title}</legend>
73+
)}
74+
<p className="text-xs text-slate-500 mb-2">
75+
No enable switch. This section only overrides Helm values — adding an enabled field in
76+
YAML has no effect.
77+
</p>
78+
{props.description && (
79+
<p className="field-description text-xs text-slate-400 mb-2">{props.description}</p>
80+
)}
81+
{props.properties.map((prop) => (
82+
<div key={prop.name}>{prop.content}</div>
83+
))}
84+
</fieldset>
85+
)
86+
}
87+
5688
if (isAddon) {
5789
const isEnabled = (formData as { enabled?: unknown } | undefined)?.enabled === true
5890
const enabledProp = props.properties.find((p) => p.name === "enabled")

‎packages/system/kubernetes-rd/cozyrds/kubernetes.yaml‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)