KubeSphere FrontendIntegration YAML 生成实战:用单菜单 JSON 一键产出规范 CRD 清单
2026/9/14 4:18:55 网站建设 项目流程

KubeSphere FrontendIntegration YAML 生成实战:用单菜单 JSON 一键产出规范 CRD 清单

【免费下载链接】kubesphereThe container platform tailored for Kubernetes multi-cloud, datacenter, and edge management ⎈ 🖥 ☁️项目地址: https://gitcode.com/GitHub_Trending/ku/kubesphere

导读

本文以 KubeSphere 仓库中的 frontend-integration-yaml 参考文档 为主线,讲解如何以一份"单菜单 + 多页面"的简化 JSON 为输入,通过官方生成器脚本快速产出可直接提交的规范FrontendIntegrationKubernetes 资源(API 组frontend-forge.kubesphere.io/v1alpha1)。读完本文,你将掌握输入 Schema 的完整字段语义、crdTableiframe两类页面变体、字段映射与规范化规则、生成器命令行用法,以及产出 YAML 后如何接入 frontend-forge 扩展的运行时部署流程。

FrontendIntegration 与简化编写模型

FrontendIntegration(下称 FI)是 frontend-forge 扩展用于声明"前端集成"的规范资源:它把一组菜单项(spec.menus[])与一组页面(spec.pages[])绑定在一起,前端运行时据此渲染 KubeSphere 控制台中的导航菜单与页面。它的 API 版本与类型为:

apiVersion: frontend-forge.kubesphere.io/v1alpha1 kind: FrontendIntegration

然而规范形态的spec.menus[]结构(含placementtypechildren嵌套)手工编写冗长且容易出错。因此,frontend-integration-yaml skill 定义了一种故意比输出更简单的作者模型:只写一个顶层menu(单个菜单)加若干pages,再由生成器自动展开为规范的spec.menus[]数组。这正是本文要讲解的核心思路——"作者写简化 JSON,生成器产出规范 YAML"。

该 skill 的职责边界很明确(见 SKILL.md):

  • 适用:生成 FI YAML、根据 CRD 快速创建集成清单、创建 iframe 型 FI 清单、把简化的单菜单配置转换为规范 YAML;
  • 不适用:排查已有 FI 资源、管理 enable/disable/delete 生命周期、检查 JSBundle/Job/控制器/状态流转、编辑清单生成规则、处理多菜单作者模型。

输入 Schema:顶层字段

生成器从stdin--input <path>读取 JSON。顶层结构如下:

{ "metadata": { "name": "required", "annotations": { "kubesphere.io/description": "optional" } }, "spec": { "enabled": true, "displayName": "optional", "builder": { "engineVersion": "optional" }, "locales": { "en": { "KEY": "Value" } } }, "menu": { "displayName": "required", "icon": "optional, defaults to GridDuotone", "placements": ["cluster"] }, "pages": [] }

各部分的语义与生成器源码中的处理逻辑(generate_frontend_integration.py)对应如下:

  • metadata.name:必填,直接映射为资源名称;metadata.annotations可选,会被原样保留(sanitize_annotations会校验 key/value 均为非空字符串)。
  • spec.enabled:可选布尔值,默认true(源码normalize_bool(..., default=True))。
  • spec.displayName/spec.builder.engineVersion/spec.locales:可选透传字段,会被原样搬运到输出spec中,不参与展开逻辑。
  • menu.displayName:必填,将成为所有展开后菜单子项的显示名来源之一。
  • menu.icon:可选,缺省时使用GridDuotone(源码常量DEFAULT_MENU_ICON)。
  • menu.placements[]:必填且至少一项,决定菜单挂在控制台的哪个层级(见下文"Placement 规则")。
  • pages[]:必填且至少一项,页面列表。

页面变体:crdTable 与 iframe

pages[]中每个页面必须声明type,当前仅支持两种取值(源码VALID_PAGE_TYPES = {"crdTable", "iframe"})。

crdTable:把 CRD 渲染成表格页面

{ "displayName": "Bundles", "key": "optional", "type": "crdTable", "crdTable": { "authKey": "optional", "group": "extensions.kubesphere.io", "version": "v1alpha1", "scope": "Cluster", "names": { "kind": "JSBundle", "plural": "jsbundles" }, "columns": [] } }

规则(与源码normalize_crd_page对应):

  • crdTable.groupcrdTable.versioncrdTable.scopecrdTable.names.plural必填
  • crdTable.names.kind可选,提供时原样透传;
  • 页面级key缺省时默认为names.plural(例如jsbundles);
  • crdTable.columns可选;缺省时按scope推导默认列(见下文"默认列");
  • crdTable.authKey可选,透传为鉴权标识。

iframe:内嵌外部页面

{ "displayName": "Dashboard", "key": "dashboard", "type": "iframe", "iframe": { "src": "https://example.test/dashboard" } }

规则:

  • key必填(iframe 无法从 CRD 推导 key);
  • iframe.src必填,指向要内嵌的页面地址。

输出形态:规范 FrontendIntegration YAML

无论输入多么简化,生成器总是输出规范形态的FrontendIntegration

apiVersion: frontend-forge.kubesphere.io/v1alpha1 kind: FrontendIntegration metadata: name: example spec: enabled: true menus: - key: example-cluster displayName: Operations icon: BoxDuotone placement: cluster type: organization children: - key: jsbundles displayName: Bundles pages: - key: jsbundles type: crdTable crdTable: group: extensions.kubesphere.io version: v1alpha1 scope: Cluster names: kind: JSBundle plural: jsbundles columns: - key: name title: NAME enableSorting: true render: type: text path: metadata.name - key: updateTime title: CREATION_TIME enableHiding: true enableSorting: true render: type: time path: metadata.creationTimestamp format: local-datetime

注意输出中menus[0].keyexample-clustermetadata.name+-+placement),menus[0].type固定为organizationchildrenpages[]推导而来。这正是 SKILL.md 中"永远把menu.placements[]展开为spec.menus[]、永远从pages[]推导children"的落地结果。

自定义列的 render 能力

通过 validate_column 可以看到,自定义列render.type支持texttimelink三种(源码VALID_RENDER_TYPES),并可携带可选的formatpatternlinkpayload字段;列级enableSortingenableHiding均须为布尔值。例如时间列常配合format: local-datetime使用。

字段映射一览

参考文档 Field Mapping 给出的完整映射关系:

  • metadata.name直接映射为资源名称;
  • metadata.annotations提供时原样保留;
  • spec.enabled缺省为true
  • menu.icon缺省为GridDuotone
  • menu.displayNamemenu.iconmenu.placements[]展开为spec.menus[]
  • 每个规范菜单 key 为${metadata.name}-${placement}
  • 每个菜单type: organization
  • pages[].displayName成为对应菜单子项children[].displayName
  • pages[].key同时成为页面 key 与子项 key。

规范化规则

Placement 规则

  • 支持的 placement 仅限clusterworkspaceglobal(源码VALID_PLACEMENTS);
  • 重复的 placement 会被拒绝;
  • 只要存在任一workspaceplacement,所有crdTable.scope一律强制为Namespaced(源码normalize_pages中的force_namespaced逻辑)。

Scope 规则

pages[].crdTable.scope接受ClusterclusterNamespacednamespacedNamespacenamespace六种写法(源码normalize_scopelower()再归并):namespaced 类取值统一归一化为Namespaced,cluster 类取值统一归一化为Cluster

默认列

省略columns时按 scope 生成默认列。Cluster范围(源码 default_columns):

columns: - enableSorting: true key: name render: path: metadata.name type: text title: NAME - enableHiding: true enableSorting: true key: updateTime render: format: local-datetime path: metadata.creationTimestamp type: time title: CREATION_TIME

Namespaced范围则在name之后、updateTime之前额外插入PROJECT(namespace)列:

columns: - enableSorting: true key: name render: path: metadata.name type: text title: NAME - enableHiding: true key: namespace render: path: metadata.namespace type: text title: PROJECT - enableHiding: true enableSorting: true key: updateTime render: format: local-datetime path: metadata.creationTimestamp type: time title: CREATION_TIME

显式列的规范化

当用户显式提供columns时,生成器会先逐列校验(key/title/render 必填,render.type 合法),再按最终 scope 执行 normalize_columns:

  • 最终 scope 为Cluster时,删除所有已存在的namespace列;
  • 最终 scope 为Namespaced时,确保恰好一个namespace列:若存在updateTime列,则插在updateTime之前;否则若存在name列,插在name之后;否则追加到末尾。

校验规则:生成器会拒绝什么

生成器在校验失败时会抛出ValidationError并以退出码 1 输出Error: ...到 stderr。被拒绝的场景包括(参考文档 Validation Rules 及源码各require_*/normalize_*函数):

  • 缺少metadata.name
  • 缺少menu.displayNamemenu.placements(placements 为空数组同样报错);
  • placement 重复;
  • 页面 key 重复;
  • crdTable必填字段缺失(group/version/scope/names.plural);
  • 缺少iframe.src
  • 输入不是合法 JSON、顶层不是对象、type不属于crdTable/iframe、render.type 非法、scope 无法识别等也会被拒绝。

使用生成器脚本

生成器为纯 Python 3 脚本 generate_frontend_integration.py,无第三方依赖。命令行接口如下:

python3 scripts/generate_frontend_integration.py [--input <path>] [--output <path>]
  • --input:JSON 作者清单路径,缺省为-,即从 stdin 读取;
  • --output:生成 YAML 的输出路径,缺省输出到 stdout。

例如,把清单写入spec.json后生成:

python3 skills/frontend-integration-yaml/scripts/generate_frontend_integration.py --input spec.json --output fi.yaml

或直接管道输入:

cat spec.json | python3 skills/frontend-integration-yaml/scripts/generate_frontend_integration.py

生成器内置了一个轻量级 YAML 序列化器(dump_yaml及其配套的format_key/format_string),会为 YAML 保留字(nulltrueyes等)、数字样字符串、含控制字符或特殊符号的字符串自动加引号,保证输出 YAML 始终可被解析。这也是官方工作流中"把生成器当作唯一真相来源、不要手工重建规范 YAML"(见 SKILL.md)的原因之一。

完整示例

示例一:纯 CRD 表格页

输入(bundles.json):

{ "metadata": { "name": "bundles" }, "menu": { "displayName": "Extensions", "icon": "BoxDuotone", "placements": ["cluster"] }, "pages": [ { "displayName": "Bundles", "type": "crdTable", "crdTable": { "group": "extensions.kubesphere.io", "version": "v1alpha1", "scope": "Cluster", "names": { "kind": "JSBundle", "plural": "jsbundles" } } } ] }

生成结果要点:

  • 输出规范FrontendIntegration资源;
  • menus[0].key = bundles-cluster
  • 页面 key 由names.plural推导为jsbundles
  • 自动生成 Cluster 默认列(name + creationTimestamp)。

示例二:crdTable 与 iframe 混合

输入(ops.json):

{ "metadata": { "name": "ops" }, "menu": { "displayName": "Operations", "icon": "AppsGearDuotone", "placements": ["cluster", "workspace"] }, "pages": [ { "displayName": "Bundles", "type": "crdTable", "crdTable": { "group": "extensions.kubesphere.io", "version": "v1alpha1", "scope": "Cluster", "names": { "plural": "jsbundles" } } }, { "displayName": "Dashboard", "key": "dashboard", "type": "iframe", "iframe": { "src": "https://example.test/dashboard" } } ] }

生成结果要点:

  • 菜单展开为ops-clusterops-workspace两个 organization 菜单;
  • 由于包含workspaceplacement,crdTable 页面的 scope 被强制改为Namespaced(即便输入写的是Cluster);
  • 自动插入PROJECT(namespace)列,使表格展示所属项目。

部署与后续运行时操作

生成出的规范 YAML 即为最终产物。将其应用进集群即可创建 FI 资源:

kubectl apply -f fi.yaml

注意:FrontendIntegration集群级资源,操作时不要加-n(参见 frontend-forge-fi-operations)。在创建、更新、启用、禁用、删除或排查 FI 之前,务必先做预检,确认 frontend-forge 扩展已就绪:

kubectl get extension frontend-forge kubectl get installplan frontend-forge -o yaml # 需要:extension 存在、installplan 存在、spec.enabled=true

FI 被控制器接管后,会触发构建 Job 并产出运行时JSBundle与 ConfigMap。排查时可参考 FI 运行时检查参考:

kubectl get fi <fi-name> -o yaml kubectl get jobs -n extension-frontend-forge -l frontend-forge.io/fi-name=<fi-name> kubectl get fi <fi-name> -o jsonpath='{.status.bundle_ref.name}{"\n"}' kubectl get jsbundle fi-<fi-name> -o yaml kubectl get configmap -n extension-frontend-forge fi-<fi-name>-config -o yaml

常用标签与注解也是排查利器:标签frontend-forge.io/fi-namefrontend-forge.io/spec-hashfrontend-forge.io/manifest-hashfrontend-forge.io/enabled,注解frontend-forge.io/build-jobfrontend-forge.io/manifest-contentfrontend-forge.io/source-spec等,均可在 FI 及其衍生对象上查到。

小结

KubeSphere 的 frontend-integration-yaml 生成器把"声明前端集成"这一高频操作压缩成了三个动作:写一份单菜单 JSON → 运行生成器脚本 → apply 规范 YAML。生成器在展开菜单、推导 key、按 scope 生成默认列、规范化显式列、强制 workspace 范围 namespaced 等方面做了全部重活,同时用严格的校验保证产物合规。理解输入 Schema、页面变体、字段映射与规范化规则后,无论是为 CRD 快速生成表格页,还是混入 iframe 页嵌入外部面板,都可以做到一次生成、直接提交。

【免费下载链接】kubesphereThe container platform tailored for Kubernetes multi-cloud, datacenter, and edge management ⎈ 🖥 ☁️项目地址: https://gitcode.com/GitHub_Trending/ku/kubesphere

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询