Skip to content

Commit

Permalink
Restore repo
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Hutton authored and Alan Hutton committed Apr 24, 2023
1 parent b5b6a3d commit 767f7ff
Show file tree
Hide file tree
Showing 548 changed files with 106,797 additions and 1 deletion.
Binary file added .DS_Store
Binary file not shown.
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# run "./make.sh alpine" first to generate envtpl
FROM alpine:3.8
COPY envtpl .
RUN mv envtpl /usr/local/bin
ENTRYPOINT [ "envtpl" ]
8 changes: 8 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2016 Tony Pujals

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
112 changes: 111 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,111 @@
# envtpl
# envtpl

`envtpl` renders [Go templates] on the command line using environment variables.

It is directly inspired by the original [envtpl], a Python tool for rendering
[Jinja2] templates.

This port was motivated by the desire to add templating support for template-driven
configuration files that needed to be part of a base Docker image without also
requiring the installation of Python. For the same reason, I decided not to add
variable support to my previous template utility [njx], which depends on Node.js.

Despite the difference between `Jinja` and `Go` templates, an attempt was made
to match the command line syntax of the original `envtpl`.

The biggest obvious difference is that `Go` template variables represent a path within
a data context, so `envtpl` variables will need to be prepended with a leading `.` to
match the keys of the internal environment variable map object (see example).

## Usage

envtpl [-o|--output outfile] [template]

* If `template` is not provided, `envtpl` reads from `stdin`
* If `outfile` is not provide, `envtpl` writes to `stdout`

## Example

`greeting.tpl`

Hello {{.USER}}

Render the template (assume the value of `$USER` is 'mary')

envtpl greeting.tpl # writes "Hello mary" to stdout

USER=bob envtpl greeting.tpl # overrides "mary" and writes "Hello bob" to stdout

echo "greetings {{.USER}}" | envtpl # writes "greetings mary" to stdout

envtpl < greeting.tpl > out.txt # writes "Hello mary" to out.txt

cat greeting.tpl | envtpl > out.txt # writes "Hello mary" to out.txt

`test/test.tpl` tests conditional functions as well as loop on environment variables. the `test/test/sh` script compares the output of envtpl with the expected output and can be used as unit test.

## Template Functions

In addition to the [standard set of template actions and functions][standard-templates]
that come with Go, `envtpl` also incorporates [sprig] for additional, commonly used functions.

For example:

echo "Greetings, {{.USER | title}}" | envtpl # writes "Greetings, Mary" to stdout

In the example, the environment name of the user `mary` is converted to `Mary` by the `title` template function.

### Other functions

To mimic the environment function for the original envtpl, an `environment` function allows to filter the environment with a prefix string

{{ range $key, $value := environment "TAG_" }}{{ $key }}="{{ $value }}"{{ end }}

filters all environment variables starting with TAG_.

## Building an envtpl executable

The `make.sh` script can be used to build the `envtpl` executable. If you provide
the `alpine` argument, it will build a binary for Alpine Linux. This build script
is intended for Docker workflows; it does not require Go support, only Docker.

To build it for another system, export the GOOS and GOARCH environment variables.

## Building an envtpl Docker image

`build.sh` can be used to create an image for `envtpl` using the provided `Dockerfile`.
It copies the `envtpl` binary from the repo directory after building it with `make.sh`.
Because the `Dockerfile` is based on the `alpine` image, be sure to first build
an executable for Alpine with the `alpine` option (`./build.sh alpine`).

## Similar Tools

As mentioned above, this tool was inspired by the original [envtpl] project and
motivated to provide something similar without adding a Python dependency to
Docker base images.

A search for similar Go-based tools turns up the following:

* [mattrobenolt/envtpl]
* [arschles/envtpl]

I haven't spent any time evaluating either yet. However, [mattrobenolt/envtpl] looks elegantly simple and [arschles/envtpl] offers tests, [glide] package management support and more template functionality using [sprig].

Neither of these two packages appear to conform to the original `envtpl` command line syntax, which was one of my goals, although I don't think this is a big deal since all of these spin-off versions use an entirely different template syntax anyway. However, at first glance at least, this variant does offer more input/output options modeled after the original.

I'm inspired by [arschles/envtpl] to add ~~[sprig] support for extended template functions~~, ~~potentially [glide] support~~, and definitely tests. This version now has [sprig] template support also (credit to [arschles/envtpl]) and uses glide for vendoring.

## License

[MIT](https://raw.githubusercontent.com/subfuzion/envtpl/master/LICENSE)


[arschles/envtpl]: https://github.com/arschles/envtpl
[envtpl]: https://github.com/andreasjansson/envtpl
[glide]: https://github.com/Masterminds/glide
[Go templates]: https://golang.org/pkg/text/template/
[Jinja2]: http://jinja.pocoo.org/docs/dev/
[mattrobenolt/envtpl]: https://github.com/mattrobenolt/envtpl
[njx]: https://github.com/subfuzion/njx
[sprig]: https://github.com/Masterminds/sprig
[standard-templates]: https://golang.org/pkg/text/template/
5 changes: 5 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash
#
# Build the subfuzion/envtpl image
#
docker build -t subfuzion/envtpl .
104 changes: 104 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package cmd

import (
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"text/template"

"github.com/Masterminds/sprig"
"github.com/spf13/cobra"
)

var err error
var output string

func checkError(err error) {
if err != nil {
log.Fatal(err)
}
}

var RootCmd = &cobra.Command{
Use: "envtpl",
Short: "Render go templates from environment variables",
Long: `Render go templates from environment variables.`,
Run: func(cmd *cobra.Command, args []string) {
// load template; if an argument is not specified, default to stdin
var t *template.Template
if len(args) > 0 {
t, err = parseFiles(args...)
checkError(err)
} else {
bytes, err := ioutil.ReadAll(os.Stdin)
checkError(err)
t, err = parse(string(bytes))
checkError(err)
}

// get environment variables to supply to the template
env := readEnv()

// get writer for rendered output; if an output file is not
// specified, default to stdout
var w io.Writer
if len(output) > 0 {
f, err := os.Create(output)
checkError(err)
defer f.Close()
w = io.Writer(f)
} else {
w = os.Stdout
}

// render the template
err := t.Execute(w, env)
checkError(err)
},
}

func Execute() {
err := RootCmd.Execute()
checkError(err)
}

func init() {
RootCmd.Flags().StringVarP(&output, "output", "o", "", "The rendered output file")
}

func parse(s string) (*template.Template, error) {
return template.New("").Funcs(sprig.TxtFuncMap()).Funcs(customFuncMap()).Parse(s)
}

func parseFiles(files ...string) (*template.Template, error) {
return template.New(filepath.Base(files[0])).Funcs(sprig.TxtFuncMap()).Funcs(customFuncMap()).ParseFiles(files...)
}

func readEnv() (env map[string]string) {
env = make(map[string]string)
for _, setting := range os.Environ() {
pair := strings.SplitN(setting, "=", 2)
env[pair[0]] = pair[1]
}
return
}

// returns key, value for all environment variables starting with prefix
func environment(prefix string) map[string]string {
env := make(map[string]string)
for _, setting := range os.Environ() {
pair := strings.SplitN(setting, "=", 2)
if strings.HasPrefix(pair[0], prefix) {
env[pair[0]] = pair[1]
}
}
return env
}

func customFuncMap() template.FuncMap {
var functionMap = map[string]interface{}{"environment": environment}
return template.FuncMap(functionMap)
}
Binary file added envtpl
Binary file not shown.
27 changes: 27 additions & 0 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package: github.com/subfuzion/envtpl
import:
- package: github.com/Masterminds/sprig
version: ^2.15.0
- package: github.com/spf13/cobra
version: ^0.0.3
- package: github.com/spf13/pflag
version: ^1.0.2
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/subfuzion/envtpl/cmd"

func main() {
cmd.Execute()
}
14 changes: 14 additions & 0 deletions make.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
#
# This script will build the executable and leave it in this directory.
#
# If the first argument to the script is set to "alpine", then it will
# build a binary for Alpine Linux.
#

IMAGE=$([ "$1" == "alpine" ] && echo "golang:1.10-alpine" || echo "golang:1.10")
SRCDIR=/go/src/github.com/subfuzion/envtpl
LDFLAGS="-s -w"

docker pull $IMAGE
docker $DOCKER_OPTIONS run -t --rm -v "$PWD":$SRCDIR -e GOOS=${GOOS:-linux} -e GOARCH=${GOARCH:-amd64} -w $SRCDIR $IMAGE go build -v -ldflags "$LDFLAGS" .
1 change: 1 addition & 0 deletions test/greeting.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello {{.USER}}
20 changes: 20 additions & 0 deletions test/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

TMPFILE=$(mktemp)
TESTDIR=$(dirname $0)
program=envtpl
cmd=$(dirname $0)/../$program

TAG_REGION=eu-west-1 TAG_DATACENTER=dc1 INTERVAL=2s OUTPUT_INFLUXDB_ENABLED=true HOSTNAME=localhost ${cmd} ${TESTDIR}/test.tpl > ${TMPFILE}
diff "${TESTDIR}/test.txt" "${TMPFILE}" >/dev/null
if [[ $? -ne 0 ]]; then
echo "$program does not produce expected result"
echo "expected result:"
cat "${TESTDIR}/test.txt"
echo "observed result:"
cat "${TMPFILE}"
rm "${TMPFILE}"
return 1
fi
echo "Tests passed successfully"
rm "${TMPFILE}"
21 changes: 21 additions & 0 deletions test/test.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[agent]
## Default data collection interval for all inputs
interval = "{{ .INTERVAL | default "10s" }}"
round_interval = {{ .ROUND_INTERVAL | default "true" }}
hostname = "{{ .HOSTNAME }}"

{{ if eq .OUTPUT_INFLUXDB_ENABLED "true" -}}
[[outputs.influxdb]]
{{- else -}}
# InfluxDB output is disabled
{{- end }}

{{ if .OUTPUT_KAFKA_ENABLED -}}
[[outputs.kafka]]
{{- else -}}
# kafka output is disabled
{{- end }}

Environment variables starting with TAG_:
{{ range $key, $value := environment "TAG_" }}{{ $key }}="{{ $value }}"
{{ end -}}
13 changes: 13 additions & 0 deletions test/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[agent]
## Default data collection interval for all inputs
interval = "2s"
round_interval = true
hostname = "localhost"

[[outputs.influxdb]]

# kafka output is disabled

Environment variables starting with TAG_:
TAG_DATACENTER="dc1"
TAG_REGION="eu-west-1"
25 changes: 25 additions & 0 deletions vendor/github.com/Masterminds/semver/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 767f7ff

Please sign in to comment.