package main import ( "encoding/json" "flag" "fmt" "html/template" "io" "io/fs" "io/ioutil" "os" "path/filepath" "strings" sprig "github.com/Masterminds/sprig/v3" ) type valFileSlice []string func (v *valFileSlice) String() string { return fmt.Sprintf("%v", *v) } func (v *valFileSlice) Set(value string) error { *v = append(*v, value) return nil } type valEnt struct { address []string v string } type valSlice []valEnt func (v *valSlice) String() string { return fmt.Sprintf("%v", *v) } func (v *valSlice) Set(value string) error { pieces := strings.Split(value, "=") if len(pieces) < 2 { return fmt.Errorf("Invalid value setting.") } *v = append(*v, valEnt{ strings.Split(pieces[0], "."), pieces[1], }) return nil } var flags struct { valuesFiles valFileSlice values valSlice } func init() { flag.Var(&flags.values, "set", "") flag.Var(&flags.valuesFiles, "f", "") flag.Parse() } func checkErr(err error) { if err != nil { fmt.Fprintf(os.Stderr, "ERROR: %+v", err) os.Exit(1) } } func expandFiles(files []string) (expFiles []string) { expFiles = []string{} for _, path := range files { fileInfo, err := os.Stat(path) checkErr(err) if fileInfo.IsDir() { filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { if err != nil { fmt.Fprintf(os.Stderr, "WARN: %+v", err) return err } if d.IsDir() { return nil } expFiles = append(expFiles, path) return nil }) } else { expFiles = append(expFiles, path) } } return } func mergeValues() (result map[string]interface{}) { result = map[string]interface{}{} for _, vf := range flags.valuesFiles { vfContent, err := ioutil.ReadFile(vf) checkErr(err) err = json.Unmarshal(vfContent, result) checkErr(err) } for i, v := range flags.values { subMap := result for _, node := range v.address { if i == len(v.address)-1 { subMap[node] = v.v } else { if _, ok := subMap[node]; !ok { subMap[node] = map[string]interface{}{} } subMap = subMap[node].(map[string]interface{}) } } } return } func main() { var err error tpl := template.New("base").Funcs(sprig.FuncMap()) if len(flag.Args()) == 0 || (len(flag.Args()) == 1 && flag.Args()[0] == "-") { var data []byte data, err = io.ReadAll(os.Stdin) checkErr(err) tpl, err = tpl.Parse(string(data)) checkErr(err) } else { tpl, err = tpl.ParseFiles(expandFiles(flag.Args())...) checkErr(err) } tpl.Execute(os.Stdout, mergeValues()) }