diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2017-11-18 10:10:27 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-11-18 10:10:27 -0500 |
| commit | 99b5cec8b37e25418bbfe2fc251f2adfd57603a2 (patch) | |
| tree | f48a5a55cb82db2ef29fceab1b99e6d0df2f8f47 | |
| parent | 59068e64a201941984630478dd26fc9e583222d7 (diff) | |
| parent | 01b39ee0955b59abdf1895b18435f1731226fcac (diff) | |
Merge pull request #233 from hairyhenderson/stdin-datasource-230
Adding support for stdin: scheme for datasources
| -rw-r--r-- | data/datasource.go | 20 | ||||
| -rw-r--r-- | data/datasource_test.go | 21 | ||||
| -rw-r--r-- | docs/content/functions/data.md | 21 |
3 files changed, 61 insertions, 1 deletions
diff --git a/data/datasource.go b/data/datasource.go index 9824e41f..ef693761 100644 --- a/data/datasource.go +++ b/data/datasource.go @@ -3,6 +3,7 @@ package data import ( "errors" "fmt" + "io" "io/ioutil" "log" "mime" @@ -22,6 +23,9 @@ import ( // logFatal is defined so log.Fatal calls can be overridden for testing var logFatalf = log.Fatalf +// stdin - for overriding in tests +var stdin io.Reader + func regExtension(ext, typ string) { err := mime.AddExtensionType(ext, typ) if err != nil { @@ -43,6 +47,7 @@ func init() { addSourceReader("http", readHTTP) addSourceReader("https", readHTTP) addSourceReader("file", readFile) + addSourceReader("stdin", readStdin) addSourceReader("vault", readVault) addSourceReader("consul", readConsul) addSourceReader("consul+http", readConsul) @@ -157,6 +162,9 @@ func ParseSource(value string) (*Source, error) { srcURL = absURL(f) } else if len(parts) == 2 { alias = parts[0] + if parts[1] == "-" { + parts[1] = "stdin://" + } var err error srcURL, err = url.Parse(parts[1]) if err != nil { @@ -296,6 +304,18 @@ func readFile(source *Source, args ...string) ([]byte, error) { return b, nil } +func readStdin(source *Source, args ...string) ([]byte, error) { + if stdin == nil { + stdin = os.Stdin + } + b, err := ioutil.ReadAll(stdin) + if err != nil { + log.Printf("Can't read %v: %#v", stdin, err) + return nil, err + } + return b, nil +} + func readHTTP(source *Source, args ...string) ([]byte, error) { if source.HC == nil { source.HC = &http.Client{Timeout: time.Second * 5} diff --git a/data/datasource_test.go b/data/datasource_test.go index a3b6f31e..ac7b884a 100644 --- a/data/datasource_test.go +++ b/data/datasource_test.go @@ -9,6 +9,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "strings" "testing" "github.com/blang/vfs" @@ -307,3 +308,23 @@ func TestInclude(t *testing.T) { actual := data.Include("foo") assert.Equal(t, contents, actual) } + +type errorReader struct{} + +func (e errorReader) Read(p []byte) (n int, err error) { + return 0, fmt.Errorf("error") +} + +func TestReadStdin(t *testing.T) { + defer func() { + stdin = nil + }() + stdin = strings.NewReader("foo") + out, err := readStdin(nil) + assert.NoError(t, err) + assert.Equal(t, []byte("foo"), out) + + stdin = errorReader{} + _, err = readStdin(nil) + assert.Error(t, err) +} diff --git a/docs/content/functions/data.md b/docs/content/functions/data.md index 18bb4f7c..0243b25b 100644 --- a/docs/content/functions/data.md +++ b/docs/content/functions/data.md @@ -11,7 +11,7 @@ A collection of functions that retrieve, parse, and convert structured data. Parses a given datasource (provided by the [`--datasource/-d`](#--datasource-d) argument). -Currently, `file://`, `http://`, `https://`, and `vault://` URLs are supported. +Currently, `file://`, `stdin://`, `http://`, `https://`, and `vault://` URLs are supported. Currently-supported formats are JSON, YAML, TOML, and CSV. @@ -34,6 +34,25 @@ $ gomplate -d person.json < input.tmpl Hello Dave ``` +### Providing datasources on standard input (`stdin`) + +Normally `stdin` is used as the input for the template, but it can also be used +to provide datasources. To do this, specify a URL with the `stdin:` scheme: + +```console +$ echo 'foo: bar' | gomplate -i '{{(ds "data").foo}}' -d data=stdin:///foo.yaml +bar +``` + +Note that the URL must have a file name with a supported extension in order for +the input to be correctly parsed. If no parsing is required (i.e. if the data +is being included verbatim with the include function), just `stdin:` is enough: + +```console +$ echo 'foo' | gomplate -i '{{ include "data" }}' -d data=stdin: +foo +``` + ### Usage with HTTP data ```console |
