diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..80e7ec9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +korvike diff --git a/app.go b/app.go new file mode 100644 index 0000000..31369ea --- /dev/null +++ b/app.go @@ -0,0 +1,96 @@ +package main + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "sync" + "text/template" + + "github.com/Luzifer/go_helpers/env" + "github.com/Luzifer/rconfig" +) + +var ( + cfg = struct { + Input string `flag:"in,i" default:"-" description:"Source to read the template from ('-' = stdin)"` + KeyPairs []string `flag:"key-value,v" default:"" description:"Key-value pairs to use in templating (-v key=value)"` + Output string `flag:"out,o" default:"-" description:"Destination to write the output to ('-' = stdout)"` + VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"` + }{} + + templateFunctions = template.FuncMap{} + templateFunctionsLock sync.Mutex + + version = "dev" +) + +func registerFunction(name string, f interface{}) error { + templateFunctionsLock.Lock() + defer templateFunctionsLock.Unlock() + if _, ok := templateFunctions[name]; ok { + return errors.New("Duplicate function for name " + name) + } + templateFunctions[name] = f + return nil +} + +func init() { + if err := rconfig.Parse(&cfg); err != nil { + log.Fatalf("Unable to parse commandline options: %s", err) + } + + if cfg.VersionAndExit { + fmt.Printf("korvike %s\n", version) + os.Exit(0) + } +} + +func openInput(f string) (io.Reader, error) { + if f == "-" { + return os.Stdin, nil + } + + if _, err := os.Stat(f); err != nil { + return nil, errors.New("Could not find file " + f) + } + + return os.Open(f) +} + +func openOutput(f string) (io.Writer, error) { + if f == "-" { + return os.Stdout, nil + } + + return os.Create(f) +} + +func main() { + in, err := openInput(cfg.Input) + if err != nil { + log.Fatalf("Unable to open input: %s", err) + } + + out, err := openOutput(cfg.Output) + if err != nil { + log.Fatalf("Unable to open output: %s", err) + } + + rawTpl, err := ioutil.ReadAll(in) + if err != nil { + log.Fatalf("Unable to read from input: %s", err) + } + + tpl, err := template.New("in").Funcs(templateFunctions).Parse(string(rawTpl)) + if err != nil { + log.Fatalf("Unable to parse template: %s", err) + } + + if err := tpl.Execute(out, env.ListToMap(cfg.KeyPairs)); err != nil { + log.Fatalf("Unable to execute template: %s", err) + } +} diff --git a/func_env.go b/func_env.go new file mode 100644 index 0000000..ea61b3c --- /dev/null +++ b/func_env.go @@ -0,0 +1,16 @@ +package main + +import "os" + +func init() { + registerFunction("env", func(name string, v ...string) string { + defaultValue := "" + if len(v) > 0 { + defaultValue = v[0] + } + if value, ok := os.LookupEnv(name); ok { + return value + } + return defaultValue + }) +}