package tmpl import ( "fmt" log "sunhpc/pkg/logger" templating "sunhpc/pkg/templating" "github.com/spf13/cobra" ) var ( tmplFile string hostname string domain string oldHostname string ip string clusterName string outputRoot string ) func newRenderCmd() *cobra.Command { cmd := &cobra.Command{ Use: "render ", Short: "渲染配置模板", Long: "根据 YAML 模板和上下文变量生成配置文件或脚本", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { tmplName := args[0] var template *templating.Template var err error // 优先使用 -f 指定的外部模版文件 if tmplFile != "" { template, err = templating.LoadTemplate(tmplFile) if err != nil { return fmt.Errorf("加载外部模板失败: %w", err) } log.Infof("✅ 外部模板 '%s' 已加载\n", tmplFile) } else { // 否则从内置模板加载 template, err = templating.LoadEmbeddedTemplate(tmplName) if err != nil { return err } log.Infof("✅ 内置模板 '%s' 已加载\n", tmplName) } ctx := templating.Context{ Node: templating.NodeInfo{ Hostname: hostname, OldHostname: oldHostname, Domain: domain, IP: ip, }, Cluster: templating.ClusterInfo{ Name: clusterName, }, } rendered, err := template.Render(ctx) if err != nil { return fmt.Errorf("模板渲染失败: %w", err) } // 处理 post 阶段 if steps, ok := rendered["post"]; ok { fmt.Println(">>> 执行 post 阶段") if err := templating.WriteFiles(steps, outputRoot); err != nil { return err } templating.PrintScripts(steps) } // 处理 configure 阶段 if steps, ok := rendered["configure"]; ok { fmt.Println(">>> 执行 configure 阶段") templating.PrintScripts(steps) } fmt.Println("✅ 模板渲染完成") return nil }, } cmd.Flags().StringVarP(&tmplFile, "file", "f", "", "指定模板文件路径(覆盖默认查找)") cmd.Flags().StringVar(&hostname, "hostname", "", "节点主机名") cmd.Flags().StringVar(&domain, "domain", "cluster.local", "DNS 域名") cmd.Flags().StringVar(&oldHostname, "old-hostname", "", "旧主机名(用于迁移)") cmd.Flags().StringVar(&ip, "ip", "", "节点 IP 地址") cmd.Flags().StringVar(&clusterName, "cluster", "default", "集群名称") cmd.Flags().StringVarP(&outputRoot, "output", "o", "/", "文件输出根目录") _ = cmd.MarkFlagRequired("hostname") return cmd }