Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/chenrui333/envtpl

Render Go templates on the command line with shell environment variables
https://github.com/chenrui333/envtpl

jinja2 jinja2-templates

Last synced: 3 months ago
JSON representation

Render Go templates on the command line with shell environment variables

Awesome Lists containing this project

README

        

# envtpl

[![main](https://github.com/chenrui333/envtpl/actions/workflows/main.yml/badge.svg)](https://github.com/chenrui333/envtpl/actions/workflows/main.yml)

This is a fork of [subfuzion/envtpl](https://github.com/subfuzion/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).

## Get it

$ go get github.com/chenrui333/envtpl/...

## Usage

envtpl [-o|--output outfile] [-m|--missingkey option] [template]

* If `template` is not provided, `envtpl` reads from `stdin`
* If `outfile` is not provided, `envtpl` writes to `stdout`
* If `missingkey` is unset or set to either `default` or `invalid`,
`envtpl` follows the default behavior of
[the golang template library](https://golang.org/pkg/text/template/#Template.Option)
and missing keys in the template will be filled in with the string
``. If `missingkey` is set to `zero`, missing keys will be
filled in with the zero value for their data type (ie: an empty
string). If `missingkey` is set to `error`, `envtpl` will fail and
an error returned to the caller.

## 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
envtpl > out.txt < greeting.tpl # same thing
cat greeting.tpl | envtpl > out.txt # same thing

unset USER; envtpl greeting.tpl # => "Hello "
unset USER; envtpl -m zero greeting.tpl # => "Hello "
unset USER; envtpl -m error greeting.tpl # => "map has no entry for key "USER"", aborts

# Use a GitHub gist with curl
curl -s https://gist.githubusercontent.com/subfuzion/d5a6e3b7c2577902408069deb1d8e4d7/raw/2e4c0b894e2983411a20ffa5ee84aeafa5c6ebfb/greeting.tpl | envtpl
# => Hello, Tony

See `test/test.tpl` for more examples, including conditional functions and looping over environment variables.

## Template Functions

### sprig
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.

For reference, see [sprig functions].

### environment

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_.

For example:

```bash
$ echo '{{ range $key, $value := environment "GO" }}{{ $key }} => {{ $value }} {{ "\n" }}{{ end }}' | envtpl
GOPATH => /Users/tony/go
GOROOT => /usr/local/go
```

## Building an envtpl Docker image

[![Docker Build Status](https://img.shields.io/docker/build/chenrui333/envtpl.svg)](https://hub.docker.com/r/chenrui333/envtpl/)

An image is available on Docker Hub [chenrui333/envtpl](https://hub.docker.com/r/chenrui333/envtpl/)

You can use run a container like this:

$ echo 'Hello {{ .NAME | title | printf "%s\n" }}' | docker run -i --rm -e NAME=world chenrui333/envtpl
Hello World

# using a gist
$ curl -s https://gist.githubusercontent.com/subfuzion/d5a6e3b7c2577902408069deb1d8e4d7/raw/2e4c0b894e2983411a20ffa5ee84aeafa5c6ebfb/greeting.tpl | docker run -i -e USER=$USER chenrui333/envtpl
Hello, Tony

To build your own local container:

$ make image

The final image is based on `scratch` and weighs in at less than 7MB:

```bash
$ docker images --format "{{ .Repository }}:{{ .Tag }} => {{ .Size }}" chenrui333/envtpl
chenrui333/envtpl:latest => 6.65MB
```

## Test

The Dockerfile for the image explicitly runs tests, so if the image
builds successfully, then the tests passed.

There is an automated build for chenrui333/envtpl on Docker Hub. Docker
Hub runs tests based on the presence of `docker-compose.test.yml`, so
there is a `docker-compose.test.file` that simply builds the image and
runs `envtpl --version`. You can test this yourself:

$ make test

## 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, tests, and uses Go 1.1. modules instead of glide.

## License

[MIT](https://raw.githubusercontent.com/chenrui333/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
[sprig functions]: http://masterminds.github.io/sprig/
[standard-templates]: https://golang.org/pkg/text/template/