Skip to content

Instantly share code, notes, and snippets.

@Spazzy757
Last active June 2, 2021 13:40
Show Gist options
  • Save Spazzy757/a3bccb7b23043d211551ea651e819bc3 to your computer and use it in GitHub Desktop.
Save Spazzy757/a3bccb7b23043d211551ea651e819bc3 to your computer and use it in GitHub Desktop.
example code used to take in yaml and template out in a file
package main
/*
* A simple templating cli that takes a yaml file and template
* and templates out to stdout
* Uses Gotemplating syntax for a more comprehensive
* understanding of the different functionalities of go templates
* visit:
* - https://docs.gomplate.ca/syntax/
* - https://golang.org/pkg/html/template/
*/
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"text/template"
"gopkg.in/yaml.v2"
)
var valuesFiles *string
var templateFiles *string
func init() {
// read flags and set the values accordingly
valuesFiles = flag.String("values", "values.yaml", "Yaml with template values")
templateFiles = flag.String("templates", "template.tmpl", "Template to inject values into")
flag.Parse()
}
//readValues reads a yaml file and unmarshals it into
// a map[string]interface
func readValues(path string) (map[string]interface{}, error) {
// read content of file
content, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("unable to read values file")
}
// initialize empty object for data
data := make(map[string]interface{}, 0)
// unmarshall file data into empty object
if err := yaml.Unmarshal(content, &data); err != nil {
return nil, fmt.Errorf("unable decode the values content")
}
return data, nil
}
func main() {
//read values file data into object
// blank data object to load files into
data := make(map[string]interface{})
// split files string into slice
files := strings.Split(*valuesFiles, ",")
// loop through each file and read data
for _, file := range files {
// get values from current file
tmpData, err := readValues(file)
if err != nil {
log.Fatal(err)
}
// merge data with previous data
// NOTE: will overide keys
data = mergeObjects(data, tmpData)
}
//read template files
// split template string into slice
tmpls := strings.Split(*templateFiles, ",")
// loop through templates and template out each
for _, tmpl := range tmpls {
// load current template
t, err := template.ParseFiles(tmpl)
if err != nil {
log.Fatal("error Parsing template: ", err)
}
//template out using values from valuesFile
// will create a file corresponding with the template
// i.e templates/config.template.xml => config.xml
_, filename := filepath.Split(tmpl)
filename = strings.ReplaceAll(filename, ".template", "")
log.Printf("creating: %v", filename)
f, _ := os.Create(filename)
err = t.Execute(f, data)
if err != nil {
log.Fatal("error executing template: ", err)
}
}
}
//mergeObjects will take two interfaces
//and add them together
//NOTE: if keys clash, object two will overwite
//object ones key
func mergeObjects(
objectOne map[string]interface{},
objectTwo map[string]interface{},
) map[string]interface{} {
data := make(map[string]interface{})
// loop through first object adding
// keys to data
for k, v := range objectOne {
if _, ok := objectOne[k]; ok {
data[k] = v
}
}
// loop through object two adding
// object keys to data
for k, v := range objectTwo {
if _, ok := objectTwo[k]; ok {
data[k] = v
}
}
return data
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment