diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b2d52ac --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +LINT_ARGS ?= ./... +DESTDIR ?= "/usr/local" + +bin: + GOOS=linux go build -o bin/templater-linux main.go + upx bin/templater-linux + +install: + cp bin/templater-linux $(DESTDIR)/bin/templater + +uninstall: + rm $(DESTDIR)/bin/templater + + +test: tidy + go clean -testcache + go test -mod=vendor -v ./... + +lint: + golangci-lint run -e '.*/pkg/mod' -e ".*/go/src" --enable-all --disable lll $(LINT_ARGS) + +tidy: + go mod tidy + +vendor: tidy + go mod vendor + +clean: + rm -rf ./bin + go clean -i -x -r -modcache + +watch: + modd + + +.PHONY: clean generate vendor lint watch tidy bin/templater diff --git a/main.go b/main.go new file mode 100644 index 0000000..8e16cbd --- /dev/null +++ b/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "fmt" + "os" + "encoding/json" + "text/template" + //"github.com/hashicorp/hcl2/gohcl" + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + //"github.com/zclconf/go-cty/cty" + //"github.com/zclconf/go-cty/cty/gocty" + ctyjson "github.com/zclconf/go-cty/cty/json" +) + +func checkErr(e error) { + if e != nil { + panic(e) + } +} + +func processGoTemplate(file string, config []byte) { + + // The JSON configuration + var confData map[string]interface{} + err := json.Unmarshal(config, &confData) + checkErr(err) + + // Read the template + data, err := os.ReadFile(file) + checkErr(err) + + + tpl, err := template.New("conf").Parse(string(data)) + checkErr(err) + + checkErr(tpl.Execute(os.Stdout,config)) + +} + +func processHCLTemplate(file string, config []byte) { + + fct, err:= os.ReadFile(file) + checkErr(err) + + expr, diags := hclsyntax.ParseTemplate(fct, file, hcl.Pos{Line:1, Column: 1}) + if diags.HasErrors() { + panic(diags.Error()) + } + + ctyType, err := ctyjson.ImpliedType(config) + checkErr(err) + varsVal, err := ctyjson.Unmarshal(config,ctyType) + checkErr(err) + + ctx := &hcl.EvalContext{ + Variables: varsVal.AsValueMap(), + } + + for n := range ctx.Variables { + if !hclsyntax.ValidIdentifier(n) { + panic(fmt.Errorf("invalid template variable name %q: must start with a letter, followed by zero or more letters, digits, and underscores", n)) + } + } + + for _, traversal := range expr.Variables() { + root := traversal.RootName() + if _, ok := ctx.Variables[root]; !ok { + panic(fmt.Errorf("vars map does not contain key %q, referenced at %s", root, traversal[0].SourceRange())) + } + } + + val, diags := expr.Value(ctx) + if diags.HasErrors() { + panic(diags.Error()) + } + + fmt.Printf("%s",val.AsString()) +} + +func main() { + // The template to process + templateType := os.Args[1] + templateFile := os.Args[2] + config := []byte(os.Args[3]) + + + if templateType == "go" { + processGoTemplate(templateFile, config) + } else if templateType == "hcl" { + processHCLTemplate(templateFile, config) + } else { + panic(fmt.Errorf("Unsupported template type")) + } +} \ No newline at end of file