package config import ( "bytes" "fmt" "strings" "text/template" "github.com/Masterminds/sprig/v3" ) // TemplateEngine handles template processing with Wild Cloud context type TemplateEngine struct { configData map[string]interface{} secretsData map[string]interface{} } // NewTemplateEngine creates a new template engine with config and secrets context func NewTemplateEngine(configMgr *Manager) (*TemplateEngine, error) { configData, err := configMgr.LoadConfig() if err != nil { return nil, fmt.Errorf("loading config: %w", err) } secretsData, err := configMgr.LoadSecrets() if err != nil { return nil, fmt.Errorf("loading secrets: %w", err) } return &TemplateEngine{ configData: configData, secretsData: secretsData, }, nil } // Process processes template content with Wild Cloud context func (t *TemplateEngine) Process(templateContent string) (string, error) { // Create template with sprig functions tmpl := template.New("wild").Funcs(sprig.TxtFuncMap()) // Add Wild Cloud specific functions tmpl = tmpl.Funcs(template.FuncMap{ // Config access function - matches gomplate .config "config": func(path string) interface{} { return t.getValueByPath(t.configData, path) }, // Secret access function - matches gomplate .secrets "secret": func(path string) interface{} { return t.getValueByPath(t.secretsData, path) }, // Direct access to config data - matches gomplate behavior "getConfig": func(path string) interface{} { return t.getValueByPath(t.configData, path) }, // Direct access to secret data - matches gomplate behavior "getSecret": func(path string) interface{} { return t.getValueByPath(t.secretsData, path) }, }) // Parse template parsed, err := tmpl.Parse(templateContent) if err != nil { return "", fmt.Errorf("parsing template: %w", err) } // Execute template with context var buf bytes.Buffer context := map[string]interface{}{ "config": t.configData, "secrets": t.secretsData, } err = parsed.Execute(&buf, context) if err != nil { return "", fmt.Errorf("executing template: %w", err) } return buf.String(), nil } // ProcessFile processes a template file with Wild Cloud context func (t *TemplateEngine) ProcessFile(templateFile string) (string, error) { // Read file content content, err := readFile(templateFile) if err != nil { return "", fmt.Errorf("reading template file: %w", err) } return t.Process(string(content)) } // getValueByPath retrieves a value from nested data using dot-notation path func (t *TemplateEngine) getValueByPath(data interface{}, path string) interface{} { if path == "" { return data } parts := strings.Split(path, ".") current := data for _, part := range parts { switch v := current.(type) { case map[string]interface{}: var exists bool current, exists = v[part] if !exists { return nil } case map[interface{}]interface{}: var exists bool current, exists = v[part] if !exists { return nil } default: return nil } } return current } // readFile is a helper to read file contents func readFile(filename string) ([]byte, error) { // This would be implemented to read from filesystem // For now, returning empty to avoid import cycles return nil, fmt.Errorf("file reading not implemented yet") } // CompileTemplate is a convenience function for one-off template processing func CompileTemplate(templateContent string, configMgr *Manager) (string, error) { engine, err := NewTemplateEngine(configMgr) if err != nil { return "", err } return engine.Process(templateContent) }