103 lines
2.5 KiB
Go
103 lines
2.5 KiB
Go
package tmpl
|
|
|
|
import (
|
|
"fmt"
|
|
"gopkg.in/yaml.v2"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
type Values = map[string]interface{}
|
|
|
|
func (c *Context) createFuncMap() template.FuncMap {
|
|
return template.FuncMap{
|
|
"readFile": c.ReadFile,
|
|
"toYaml": ToYaml,
|
|
"fromYaml": FromYaml,
|
|
"setValueAtPath": SetValueAtPath,
|
|
"requiredEnv": RequiredEnv,
|
|
}
|
|
}
|
|
|
|
func (c *Context) ReadFile(filename string) (string, error) {
|
|
path := filepath.Join(c.basePath, filename)
|
|
|
|
bytes, err := c.readFile(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(bytes), nil
|
|
}
|
|
|
|
func ToYaml(v interface{}) (string, error) {
|
|
data, err := yaml.Marshal(v)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(data), nil
|
|
}
|
|
|
|
func FromYaml(str string) (Values, error) {
|
|
m := Values{}
|
|
|
|
if err := yaml.Unmarshal([]byte(str), &m); err != nil {
|
|
return nil, err
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func SetValueAtPath(path string, value interface{}, values Values) (Values, error) {
|
|
var current interface{}
|
|
current = values
|
|
components := strings.Split(path, ".")
|
|
pathToMap := components[:len(components)-1]
|
|
key := components[len(components)-1]
|
|
for _, k := range pathToMap {
|
|
var elem interface{}
|
|
|
|
switch typedCurrent := current.(type) {
|
|
case map[string]interface{}:
|
|
v, exists := typedCurrent[k]
|
|
if !exists {
|
|
return nil, fmt.Errorf("failed to set value at path \"%s\": value for key \"%s\" does not exist", path, k)
|
|
}
|
|
elem = v
|
|
case map[interface{}]interface{}:
|
|
v, exists := typedCurrent[k]
|
|
if !exists {
|
|
return nil, fmt.Errorf("failed to set value at path \"%s\": value for key \"%s\" does not exist", path, k)
|
|
}
|
|
elem = v
|
|
default:
|
|
return nil, fmt.Errorf("failed to set value at path \"%s\": value for key \"%s\" was not a map", path, k)
|
|
}
|
|
|
|
switch typedElem := elem.(type) {
|
|
case map[string]interface{}, map[interface{}]interface{}:
|
|
current = typedElem
|
|
default:
|
|
return nil, fmt.Errorf("failed to set value at path \"%s\": value for key \"%s\" was not a map", path, k)
|
|
}
|
|
}
|
|
|
|
switch typedCurrent := current.(type) {
|
|
case map[string]interface{}:
|
|
typedCurrent[key] = value
|
|
case map[interface{}]interface{}:
|
|
typedCurrent[key] = value
|
|
default:
|
|
return nil, fmt.Errorf("failed to set value at path \"%s\": value for key \"%s\" was not a map", path, key)
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
func RequiredEnv(name string) (string, error) {
|
|
if val, exists := os.LookupEnv(name); exists && len(val) > 0 {
|
|
return val, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("required env var `%s` is not set", name)
|
|
}
|