Skip to content

Commit e04fc61

Browse files
fix(dashboard): say which cluster addons are always on
cilium, coredns and verticalPodAutoscaler carry only valuesOverride and no enabled field, and the addon template keys its toggle off the presence of enabled, so those three rendered as plain groups in the same list as the toggleable addons, reading as a switch that failed to appear. What the v1.4.2 report in #3108 did next is the part worth being exact about. Setting <addon>.enabled: true in the YAML editor is accepted: the schema sets no additionalProperties, so the API stores the field and echoes it back, and it looks like it worked. Nothing reads it. No template references addons.cilium.enabled, and cilium's own HelmRelease is gated on the platform-supplied _namespace.etcd rather than on anything reachable from addons. So the toggle a user reaches for is a silent no-op that confirms itself. Verified against a live API rather than read off the schema: a server-side dry run returns {"enabled":true,"valuesOverride":{}}. The issue names two of the three; verticalPodAutoscaler has the identical shape and was verified in a browser alongside them. Fixes #3108 Assisted-By: Claude <[email protected]> Signed-off-by: Myasnikov Daniil <[email protected]>
1 parent b9a996b commit e04fc61

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { describe, expect, it } from "vitest"
2+
import { render, screen } from "@testing-library/react"
3+
import { CustomObjectFieldTemplate } from "./CustomObjectFieldTemplate.tsx"
4+
5+
const prop = (name: string) => ({
6+
name,
7+
content: <div data-testid={`field-${name}`} />,
8+
disabled: false,
9+
readonly: false,
10+
hidden: false,
11+
})
12+
13+
const base = {
14+
idSchema: { $id: "root_addons_cilium" },
15+
schema: {},
16+
title: "cilium",
17+
description: "Cilium CNI plugin.",
18+
formData: {},
19+
} as never
20+
21+
describe("mandatory addons render as always on", () => {
22+
it("says so when the object carries only valuesOverride", () => {
23+
render(
24+
<CustomObjectFieldTemplate {...(base as object)} properties={[prop("valuesOverride")]} />,
25+
)
26+
expect(screen.getByText(/Always on/)).toBeTruthy()
27+
expect(screen.queryByRole("checkbox")).toBeNull()
28+
})
29+
30+
it("leaves a toggleable addon alone", () => {
31+
render(
32+
<CustomObjectFieldTemplate
33+
{...(base as object)}
34+
properties={[prop("enabled"), prop("valuesOverride")]}
35+
/>,
36+
)
37+
expect(screen.queryByText(/Always on/)).toBeNull()
38+
expect(screen.getByTestId("field-enabled")).toBeTruthy()
39+
})
40+
})

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

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

56+
// A mandatory addon carries only its overrides and no 'enabled', because it
57+
// is always installed. Rendered as a plain group it looks like a toggleable
58+
// addon whose switch is missing, which is how users end up setting
59+
// `<addon>.enabled: true` in YAML, where it is an unknown field and does
60+
// nothing. Say it is always on instead.
61+
const isAlwaysOnAddon =
62+
!hasEnabledField &&
63+
props.properties.length > 0 &&
64+
props.properties.every((p) => p.name === "valuesOverride")
65+
66+
if (isAlwaysOnAddon) {
67+
return (
68+
<fieldset id={props.idSchema.$id} className="border border-slate-200 rounded-lg p-3 mb-3">
69+
{props.title && (
70+
<legend className="text-xs font-semibold text-slate-700 px-1">{props.title}</legend>
71+
)}
72+
<p className="text-xs text-slate-500 mb-2">
73+
Always on. This component is required and cannot be disabled.
74+
</p>
75+
{props.description && (
76+
<p className="field-description text-xs text-slate-400 mb-2">{props.description}</p>
77+
)}
78+
{props.properties.map((prop) => (
79+
<div key={prop.name}>{prop.content}</div>
80+
))}
81+
</fieldset>
82+
)
83+
}
84+
5685
if (isAddon) {
5786
const isEnabled = (formData as any)?.enabled === true
5887
const enabledProp = props.properties.find((p) => p.name === "enabled")

0 commit comments

Comments
 (0)