// K8s ClusterRole Schema - 由 ConfTemplate 生成 // 生成时间: 自动生成 export const k8sClusterRoleSchema = { id: 'k8s-clusterrole', name: 'K8s ClusterRole', icon: 'ShieldCheck', category: '云原生', description: 'Kubernetes 集群级 RBAC 角色', format: 'yaml', fileName: 'clusterrole.yaml', groups: [ { title: '基础信息', fields: [ { key: 'name', label: 'ClusterRole 名称', type: 'text', placeholder: 'my-cluster-role', default: 'my-cluster-role', required: true, tip: '将用作 ClusterRole 的 metadata.name', }, ], }, { title: '权限规则', fields: [ { key: 'resources', label: '资源类型', type: 'select', multiple: true, options: [ { label: 'Pods', value: 'pods' }, { label: 'Services', value: 'services' }, { label: 'ConfigMaps', value: 'configmaps' }, { label: 'Deployments', value: 'deployments' }, { label: 'Secrets', value: 'secrets' }, { label: 'Nodes', value: 'nodes' }, { label: 'Namespaces', value: 'namespaces' }, { label: 'All (*)', value: '*' }, ], default: ['pods'], tip: '可多选,选择要授权的资源类型', }, { key: 'verbs', label: '操作动词', type: 'select', multiple: true, options: [ { label: 'Get (读取)', value: 'get' }, { label: 'List (列表)', value: 'list' }, { label: 'Watch (监听)', value: 'watch' }, { label: 'Create (创建)', value: 'create' }, { label: 'Update (更新)', value: 'update' }, { label: 'Delete (删除)', value: 'delete' }, { label: 'Patch (补丁)', value: 'patch' }, { label: 'All (*)', value: '*' }, ], default: ['get', 'list', 'watch'], tip: '可多选,选择允许的操作', }, { key: 'apiGroups', label: 'API 组', type: 'text', placeholder: '"" (核心组留空)', default: '', tip: 'API 组,核心资源(如 pods, services)留空', }, ], }, ], } function yamlScalar(v) { if (v === null || v === undefined) return '' if (typeof v === 'number' || typeof v === 'boolean') return String(v) const s = String(v) if (/[:#\n"'`]|^[\s\-]|[\s]$/.test(s) || /^(true|false|null|yes|no|on|off|~)$/i.test(s)) { return JSON.stringify(s) } return s } function isEmptyMapping(o) { if (!o || typeof o !== 'object' || Array.isArray(o)) return false return Object.values(o).every(v => v === null || v === undefined || v === '' || (typeof v === 'object' && isEmptyMapping(v))) } function toYaml(obj, baseIndent = '') { const lines = [] for (const [key, value] of Object.entries(obj)) { if (value === null || value === undefined || value === '') continue if (Array.isArray(value)) { const items = value.filter(v => v !== null && v !== undefined && v !== '') if (!items.length) continue lines.push(`${baseIndent}${key}:`) for (const item of items) { if (item && typeof item === 'object' && !Array.isArray(item)) { if (isEmptyMapping(item)) continue const entries = Object.entries(item).filter(([, v]) => v !== null && v !== undefined && v !== '') if (!entries.length) continue const childIndent = baseIndent + ' ' const subAllIndent = childIndent + ' ' const subObj = {} for (const [k, v] of entries) subObj[k] = v const subRendered = toYaml(subObj, subAllIndent) const subLines = subRendered.split('\n') if (subLines[0].startsWith(subAllIndent)) { subLines[0] = childIndent + '- ' + subLines[0].slice(subAllIndent.length) } else { subLines[0] = childIndent + '- ' + subLines[0].trimStart() } lines.push(...subLines) } else { lines.push(`${baseIndent} - ${yamlScalar(item)}`) } } } else if (typeof value === 'object') { if (isEmptyMapping(value)) { lines.push(`${baseIndent}${key}: {}`) continue } lines.push(`${baseIndent}${key}:`) const childIndent = baseIndent + ' ' lines.push(toYaml(value, childIndent)) } else { lines.push(`${baseIndent}${key}: ${yamlScalar(value)}`) } } return lines.join('\n') } export function generateK8sClusterRoleYaml(config) { const resources = Array.isArray(config.resources) ? config.resources : [config.resources || 'pods'] const verbs = Array.isArray(config.verbs) ? config.verbs : [config.verbs || 'get'] const apiGroups = config.apiGroups !== undefined && config.apiGroups !== '' ? config.apiGroups.split(',').map(g => g.trim()) : [''] const rule = { apiGroups, resources, verbs, } const clusterRole = { apiVersion: 'rbac.authorization.k8s.io/v1', kind: 'ClusterRole', metadata: { name: config.name, }, rules: [rule], } const header = `# K8s ClusterRole - 由 ConfTemplate 生成 # 生成时间: ${new Date().toLocaleString('zh-CN')} # 部署命令: kubectl apply -f ${config.fileName || 'clusterrole.yaml'} ` return header + '\n' + toYaml(clusterRole) }