package template import ( "bytes" "context" "encoding/json" "os" "strings" "github.com/BurntSushi/toml" "github.com/pkg/errors" "go.yaml.in/yaml/v3" ) func file(ctx context.Context, templateVars any, errorOnMissing bool) func(v string) (string, error) { return func(v string) (string, error) { if v == "" { return "", nil } fileBytes, err := os.ReadFile(os.ExpandEnv(v)) if err != nil { return "", errors.Wrap(err, "failed to read file") } renderedBytes, err := ExecuteFileTemplate(ctx, string(fileBytes), templateVars, errorOnMissing) if err != nil { return "", errors.Wrap(err, "failed to render file") } return string(bytes.TrimSpace(renderedBytes)), nil } } // toYAML takes an interface, marshals it to yaml, and returns a string. It will // always return a string, even on marshal error (empty string). // // This is designed to be called from a template. func toYAML(v any) string { data, err := yaml.Marshal(v) if err != nil { return err.Error() } return strings.TrimSuffix(string(data), "\n") } func toYAMLPretty(v any) string { var data bytes.Buffer encoder := yaml.NewEncoder(&data) encoder.SetIndent(2) err := encoder.Encode(v) if err != nil { return err.Error() } return strings.TrimSuffix(data.String(), "\n") } // fromYAML converts a YAML document into a map[string]any. // // This is not a general-purpose YAML parser, and will not parse all valid // YAML documents. Additionally, because its intended use is within templates // it tolerates errors. It will insert the returned error message string into // m["Error"] in the returned map. func fromYAML(str string) map[string]any { m := map[string]any{} if err := yaml.Unmarshal([]byte(str), &m); err != nil { m["Error"] = err.Error() } return m } // fromYAMLArray converts a YAML array into a []any. // // This is not a general-purpose YAML parser, and will not parse all valid // YAML documents. Additionally, because its intended use is within templates // it tolerates errors. It will insert the returned error message string as // the first and only item in the returned array. func fromYAMLArray(str string) []any { var a []any if err := yaml.Unmarshal([]byte(str), &a); err != nil { a = []any{err.Error()} } return a } // toTOML takes an interface, marshals it to toml, and returns a string. It will // always return a string, even on marshal error (empty string). // // This is designed to be called from a template. func toTOML(v any) string { b := bytes.NewBuffer(nil) e := toml.NewEncoder(b) err := e.Encode(v) if err != nil { return err.Error() } return b.String() } // fromTOML converts a TOML document into a map[string]any. // // This is not a general-purpose TOML parser, and will not parse all valid // TOML documents. Additionally, because its intended use is within templates // it tolerates errors. It will insert the returned error message string into // m["Error"] in the returned map. func fromTOML(str string) map[string]any { m := make(map[string]any) if err := toml.Unmarshal([]byte(str), &m); err != nil { m["Error"] = err.Error() } return m } // toJSON takes an interface, marshals it to json, and returns a string. It will // always return a string, even on marshal error (empty string). // // This is designed to be called from a template. func toJSON(v any) string { data, err := json.Marshal(v) if err != nil { return err.Error() } return string(data) } // fromJSON converts a JSON document into a map[string]any. // // This is not a general-purpose JSON parser, and will not parse all valid // JSON documents. Additionally, because its intended use is within templates // it tolerates errors. It will insert the returned error message string into // m["Error"] in the returned map. func fromJSON(str string) map[string]any { m := make(map[string]any) if err := json.Unmarshal([]byte(str), &m); err != nil { m["Error"] = err.Error() } return m } // fromJSONArray converts a JSON array into a []any. // // This is not a general-purpose JSON parser, and will not parse all valid // JSON documents. Additionally, because its intended use is within templates // it tolerates errors. It will insert the returned error message string as // the first and only item in the returned array. func fromJSONArray(str string) []any { var a []any if err := json.Unmarshal([]byte(str), &a); err != nil { a = []any{err.Error()} } return a }