diff options
| -rw-r--r-- | config.go | 6 | ||||
| -rw-r--r-- | data/datasource.go | 8 | ||||
| -rw-r--r-- | data/datasource_stdin.go | 8 | ||||
| -rw-r--r-- | go.sum | 16 | ||||
| -rw-r--r-- | gomplate_test.go | 5 | ||||
| -rw-r--r-- | internal/cmd/config.go | 4 | ||||
| -rw-r--r-- | internal/cmd/config_test.go | 22 | ||||
| -rw-r--r-- | internal/cmd/main.go | 10 | ||||
| -rw-r--r-- | internal/cmd/main_test.go | 8 | ||||
| -rw-r--r-- | internal/config/configfile.go | 18 | ||||
| -rw-r--r-- | plugins.go | 5 | ||||
| -rw-r--r-- | template.go | 95 | ||||
| -rw-r--r-- | template_test.go | 84 |
13 files changed, 142 insertions, 147 deletions
@@ -2,9 +2,11 @@ package gomplate import ( "io" + "os" "strings" "github.com/hairyhenderson/gomplate/v3/internal/config" + "github.com/hairyhenderson/gomplate/v3/internal/iohelpers" ) // Config - values necessary for rendering templates with gomplate. @@ -127,7 +129,9 @@ func (o *Config) toNewConfig() (*config.Config, error) { LDelim: o.LDelim, RDelim: o.RDelim, Templates: o.Templates, - OutWriter: o.Out, + Stdin: os.Stdin, + Stdout: &iohelpers.NopCloser{Writer: o.Out}, + Stderr: os.Stderr, } err := cfg.ParsePluginFlags(o.Plugins) if err != nil { diff --git a/data/datasource.go b/data/datasource.go index 147ba013..0f2c44fa 100644 --- a/data/datasource.go +++ b/data/datasource.go @@ -3,7 +3,6 @@ package data import ( "context" "fmt" - "io" "mime" "net/http" "net/url" @@ -19,9 +18,6 @@ import ( "github.com/hairyhenderson/gomplate/v3/vault" ) -// stdin - for overriding in tests -var stdin io.Reader - func regExtension(ext, typ string) { err := mime.AddExtensionType(ext, typ) if err != nil { @@ -114,6 +110,10 @@ func NewData(datasourceArgs, headerArgs []string) (*Data, error) { // FromConfig - internal use only! func FromConfig(ctx context.Context, cfg *config.Config) *Data { + // XXX: This is temporary, and will be replaced with something a bit cleaner + // when datasources are refactored + stdin = cfg.Stdin + sources := map[string]*Source{} for alias, d := range cfg.DataSources { sources[alias] = &Source{ diff --git a/data/datasource_stdin.go b/data/datasource_stdin.go index f23905d2..8216573b 100644 --- a/data/datasource_stdin.go +++ b/data/datasource_stdin.go @@ -1,16 +1,16 @@ package data import ( + "io" "io/ioutil" - "os" "github.com/pkg/errors" ) +// stdin - for overriding in tests +var stdin io.Reader + func readStdin(source *Source, args ...string) ([]byte, error) { - if stdin == nil { - stdin = os.Stdin - } b, err := ioutil.ReadAll(stdin) if err != nil { return nil, errors.Wrapf(err, "Can't read %s", stdin) @@ -105,9 +105,7 @@ github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZo github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.36.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.36.19 h1:zbJZKkxeDiYxUYFjymjWxPye+qa1G2gRVyhIzZrB9zA= -github.com/aws/aws-sdk-go v1.36.19/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.36.23/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.36.28 h1:JVRN7BZgwQ31SQCBwG5QM445+ynJU0ruKu+miFIijYY= github.com/aws/aws-sdk-go v1.36.28/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -266,9 +264,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.3 h1:twObb+9XcuH5B9V1TBCvvvZoO6iEdILi2a76PYn5rJI= -github.com/google/uuid v1.1.3/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.4/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.4.0 h1:kXcsA/rIGzJImVqPdhfnr6q0xsS9gU0515q1EPpJ9fE= github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= @@ -511,18 +507,16 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.2 h1:60ZHIOcsJlo3bJm9CbTVu7OSqT2mxaEmyQbK2NwCkn0= -github.com/ugorji/go v1.2.2/go.mod h1:bitgyERdV7L7Db/Z5gfd5v2NQMNhhiFiZwpgMw2SP7k= +github.com/ugorji/go v1.2.3 h1:WbFSXLxDFKVN69Sk8t+XHGzVCD7R8UoAATR8NqZgTbk= github.com/ugorji/go v1.2.3/go.mod h1:5l8GZ8hZvmL4uMdy+mhCO1LjswGRYco9Q3HfuisB21A= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.2 h1:08Gah8d+dXj4cZNUHhtuD/S4PXD5WpVbj5B8/ClELAQ= -github.com/ugorji/go/codec v1.2.2/go.mod h1:OM8g7OAy52uYl3Yk+RE/3AS1nXFn1Wh4PPLtupCxbuU= +github.com/ugorji/go/codec v1.2.3 h1:/mVYEV+Jo3IZKeA5gBngN0AvNnQltEDkR+eQikkWQu0= github.com/ugorji/go/codec v1.2.3/go.mod h1:5FxzDJIgeiWJZslYHPj+LS1dq1ZBQVelZFnjsFGI/Uc= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= diff --git a/gomplate_test.go b/gomplate_test.go index 1d569958..797eb87e 100644 --- a/gomplate_test.go +++ b/gomplate_test.go @@ -16,7 +16,6 @@ import ( "github.com/hairyhenderson/gomplate/v3/conv" "github.com/hairyhenderson/gomplate/v3/data" "github.com/hairyhenderson/gomplate/v3/env" - "github.com/hairyhenderson/gomplate/v3/internal/iohelpers" "github.com/stretchr/testify/assert" ) @@ -156,10 +155,8 @@ func TestCustomDelim(t *testing.T) { } func TestRunTemplates(t *testing.T) { - defer func() { Stdout = os.Stdout }() buf := &bytes.Buffer{} - Stdout = &iohelpers.NopCloser{Writer: buf} - config := &Config{Input: "foo", OutputFiles: []string{"-"}} + config := &Config{Input: "foo", OutputFiles: []string{"-"}, Out: buf} err := RunTemplates(config) assert.NoError(t, err) assert.Equal(t, "foo", buf.String()) diff --git a/internal/cmd/config.go b/internal/cmd/config.go index 3db450af..f45f5ff1 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -48,6 +48,10 @@ func loadConfig(cmd *cobra.Command, args []string) (*config.Config, error) { return nil, err } + cfg.Stdin = cmd.InOrStdin() + cfg.Stdout = cmd.OutOrStdout() + cfg.Stderr = cmd.ErrOrStderr() + // reset defaults before validation cfg.ApplyDefaults() diff --git a/internal/cmd/config_test.go b/internal/cmd/config_test.go index aa5e09f3..1bc82e09 100644 --- a/internal/cmd/config_test.go +++ b/internal/cmd/config_test.go @@ -1,6 +1,7 @@ package cmd import ( + "bytes" "context" "fmt" "os" @@ -63,7 +64,12 @@ func TestLoadConfig(t *testing.T) { fs = afero.NewMemMapFs() defer func() { fs = afero.NewOsFs() }() + stdin, stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}, &bytes.Buffer{} cmd := &cobra.Command{} + cmd.SetIn(stdin) + cmd.SetOut(stdout) + cmd.SetErr(stderr) + cmd.Args = optionalExecArgs cmd.Flags().StringSlice("file", []string{"-"}, "...") cmd.Flags().StringSlice("out", []string{"-"}, "...") @@ -80,9 +86,11 @@ func TestLoadConfig(t *testing.T) { OutputFiles: []string{"-"}, LDelim: "{{", RDelim: "}}", - PostExecInput: os.Stdin, - OutWriter: os.Stdout, + PostExecInput: stdin, PluginTimeout: 5 * time.Second, + Stdin: stdin, + Stdout: stdout, + Stderr: stderr, } assert.NoError(t, err) assert.EqualValues(t, expected, out) @@ -94,9 +102,11 @@ func TestLoadConfig(t *testing.T) { OutputFiles: []string{"-"}, LDelim: "{{", RDelim: "}}", - PostExecInput: os.Stdin, - OutWriter: os.Stdout, + PostExecInput: stdin, PluginTimeout: 5 * time.Second, + Stdin: stdin, + Stdout: out.Stdout, + Stderr: stderr, } assert.NoError(t, err) assert.EqualValues(t, expected, out) @@ -110,9 +120,11 @@ func TestLoadConfig(t *testing.T) { ExecPipe: true, PostExec: []string{"tr", "[a-z]", "[A-Z]"}, PostExecInput: out.PostExecInput, - OutWriter: out.PostExecInput, OutputFiles: []string{"-"}, PluginTimeout: 5 * time.Second, + Stdin: stdin, + Stdout: out.Stdout, + Stderr: stderr, } assert.NoError(t, err) assert.EqualValues(t, expected, out) diff --git a/internal/cmd/main.go b/internal/cmd/main.go index 3c7862d5..9217a725 100644 --- a/internal/cmd/main.go +++ b/internal/cmd/main.go @@ -18,7 +18,7 @@ import ( ) // postRunExec - if templating succeeds, the command following a '--' will be executed -func postRunExec(ctx context.Context, cfg *config.Config) error { +func postRunExec(ctx context.Context, cfg *config.Config, stdout, stderr io.Writer) error { args := cfg.PostExec if len(args) > 0 { log := zerolog.Ctx(ctx) @@ -29,8 +29,8 @@ func postRunExec(ctx context.Context, cfg *config.Config) error { // nolint: gosec c := exec.CommandContext(ctx, name, args...) c.Stdin = cfg.PostExecInput - c.Stderr = os.Stderr - c.Stdout = os.Stdout + c.Stderr = stderr + c.Stdout = stdout // make sure all signals are propagated sigs := make(chan os.Signal, 1) @@ -98,7 +98,7 @@ func NewGomplateCmd() *cobra.Command { // Note: once stdin/out/err are externalized we should only do this // if stdout isn't ending with its own newline! if len(cfg.OutputFiles) == 0 || (len(cfg.OutputFiles) == 1 && cfg.OutputFiles[0] == "-") && !cfg.ExecPipe { - fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(cmd.ErrOrStderr(), "\n") } log.Debug().Int("templatesRendered", gomplate.Metrics.TemplatesProcessed). Int("errors", gomplate.Metrics.Errors). @@ -108,7 +108,7 @@ func NewGomplateCmd() *cobra.Command { if err != nil { return err } - return postRunExec(ctx, cfg) + return postRunExec(ctx, cfg, cmd.OutOrStdout(), cmd.ErrOrStderr()) }, Args: optionalExecArgs, } diff --git a/internal/cmd/main_test.go b/internal/cmd/main_test.go index 5c688443..678d5979 100644 --- a/internal/cmd/main_test.go +++ b/internal/cmd/main_test.go @@ -1,6 +1,7 @@ package cmd import ( + "bytes" "context" "testing" @@ -47,4 +48,11 @@ func TestRunMain(t *testing.T) { err = Main(ctx, []string{"--bogus"}, nil, nil, nil) assert.Error(t, err) + + stdin := &bytes.Buffer{} + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + err = Main(ctx, []string{"-i", "hello"}, stdin, stdout, stderr) + assert.NoError(t, err) + assert.Equal(t, "hello", stdout.String()) } diff --git a/internal/config/configfile.go b/internal/config/configfile.go index a20c95cb..9969648e 100644 --- a/internal/config/configfile.go +++ b/internal/config/configfile.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/hairyhenderson/gomplate/v3/internal/iohelpers" "github.com/pkg/errors" "gopkg.in/yaml.v3" ) @@ -59,8 +60,11 @@ type Config struct { ExtraHeaders map[string]http.Header `yaml:"-"` // internal use only, can't be injected in YAML - PostExecInput io.ReadWriter `yaml:"-"` - OutWriter io.Writer `yaml:"-"` + PostExecInput io.Reader `yaml:"-"` + + Stdin io.Reader `yaml:"-"` + Stdout io.Writer `yaml:"-"` + Stderr io.Writer `yaml:"-"` } var cfgContextKey = struct{}{} @@ -452,12 +456,14 @@ func (c *Config) ApplyDefaults() { } if c.ExecPipe { - c.PostExecInput = &bytes.Buffer{} - c.OutWriter = c.PostExecInput + pipe := &bytes.Buffer{} + c.PostExecInput = pipe c.OutputFiles = []string{"-"} + + // --exec-pipe redirects standard out to the out pipe + c.Stdout = &iohelpers.NopCloser{Writer: pipe} } else { - c.PostExecInput = os.Stdin - c.OutWriter = os.Stdout + c.PostExecInput = c.Stdin } if c.PluginTimeout == 0 { @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "io" "os" "os/exec" "os/signal" @@ -23,6 +24,7 @@ func bindPlugins(ctx context.Context, cfg *config.Config, funcMap template.FuncM name: k, path: v, timeout: cfg.PluginTimeout, + stderr: cfg.Stderr, } if _, ok := funcMap[plugin.name]; ok { return fmt.Errorf("function %q is already bound, and can not be overridden", plugin.name) @@ -37,6 +39,7 @@ type plugin struct { name, path string timeout time.Duration ctx context.Context + stderr io.Writer } // builds a command that's appropriate for running scripts @@ -78,7 +81,7 @@ func (p *plugin) run(args ...interface{}) (interface{}, error) { defer cancel() c := exec.CommandContext(ctx, name, a...) c.Stdin = nil - c.Stderr = os.Stderr + c.Stderr = p.stderr outBuf := &bytes.Buffer{} c.Stdout = outBuf diff --git a/template.go b/template.go index 7d1e1bbf..fe50d069 100644 --- a/template.go +++ b/template.go @@ -20,12 +20,8 @@ import ( const gomplateignore = ".gomplateignore" // for overriding in tests -var stdin io.ReadCloser = os.Stdin var fs = afero.NewOsFs() -// Stdout allows overriding the writer to use when templates are written to stdout ("-"). -var Stdout io.WriteCloser = os.Stdout - // tplate - models a gomplate template file... type tplate struct { name string @@ -73,22 +69,24 @@ func (t *tplate) toGoTemplate(g *gomplate) (tmpl *template.Template, err error) return tmpl, nil } -// loadContents - reads the template in _once_ if it hasn't yet been read. Uses the name! -func (t *tplate) loadContents() (err error) { - if t.contents == "" { - t.contents, err = readInput(t.name) +// loadContents - reads the template +func (t *tplate) loadContents(in io.Reader) ([]byte, error) { + if in == nil { + f, err := fs.OpenFile(t.name, os.O_RDONLY, 0) + if err != nil { + return nil, fmt.Errorf("failed to open %s: %w", t.name, err) + } + // nolint: errcheck + defer f.Close() + in = f } - return err -} -func (t *tplate) addTarget(cfg *config.Config) (err error) { - if t.name == "<arg>" && t.targetPath == "" { - t.targetPath = "-" - } - if t.target == nil { - t.target, err = openOutFile(cfg, t.targetPath, t.mode, t.modeOverride) + b, err := ioutil.ReadAll(in) + if err != nil { + return nil, fmt.Errorf("failed to load contents of %s: %w", t.name, err) } - return err + + return b, nil } // gatherTemplates - gather and prepare input template(s) and output file(s) for rendering @@ -99,11 +97,6 @@ func gatherTemplates(cfg *config.Config, outFileNamer func(string) (string, erro return nil, err } - // --exec-pipe redirects standard out to the out pipe - if cfg.OutWriter != nil { - Stdout = &iohelpers.NopCloser{Writer: cfg.OutWriter} - } - switch { // the arg-provided input string gets a special name case cfg.Input != "": @@ -133,14 +126,31 @@ func gatherTemplates(cfg *config.Config, outFileNamer func(string) (string, erro return processTemplates(cfg, templates) } +// processTemplates - reads data into the given templates as necessary and opens +// outputs for writing as necessary func processTemplates(cfg *config.Config, templates []*tplate) ([]*tplate, error) { for _, t := range templates { - if err := t.loadContents(); err != nil { - return nil, err + if t.contents == "" { + var in io.Reader + if t.name == "-" { + in = cfg.Stdin + } + + b, err := t.loadContents(in) + if err != nil { + return nil, err + } + + t.contents = string(b) } - if err := t.addTarget(cfg); err != nil { - return nil, err + if t.target == nil { + out, err := openOutFile(cfg, t.targetPath, t.mode, t.modeOverride) + if err != nil { + return nil, err + } + + t.target = out } } @@ -225,11 +235,19 @@ func fileToTemplates(inFile, outFile string, mode os.FileMode, modeOverride bool return tmpl, nil } +func stdout(cfg *config.Config) io.WriteCloser { + wc, ok := cfg.Stdout.(io.WriteCloser) + if ok { + return wc + } + return &iohelpers.NopCloser{Writer: cfg.Stdout} +} + func openOutFile(cfg *config.Config, filename string, mode os.FileMode, modeOverride bool) (out io.WriteCloser, err error) { if cfg.SuppressEmpty { out = iohelpers.NewEmptySkipper(func() (io.WriteCloser, error) { if filename == "-" { - return Stdout, nil + return stdout(cfg), nil } return createOutFile(filename, mode, modeOverride) }) @@ -237,7 +255,7 @@ func openOutFile(cfg *config.Config, filename string, mode os.FileMode, modeOver } if filename == "-" { - return Stdout, nil + return stdout(cfg), nil } return createOutFile(filename, mode, modeOverride) } @@ -277,24 +295,3 @@ func createOutFile(filename string, mode os.FileMode, modeOverride bool) (out io return out, err } - -func readInput(filename string) (string, error) { - var err error - var inFile io.ReadCloser - if filename == "-" { - inFile = stdin - } else { - inFile, err = fs.OpenFile(filename, os.O_RDONLY, 0) - if err != nil { - return "", fmt.Errorf("failed to open %s: %w", filename, err) - } - // nolint: errcheck - defer inFile.Close() - } - bytes, err := ioutil.ReadAll(inFile) - if err != nil { - err = fmt.Errorf("read failed for %s: %w", filename, err) - return "", err - } - return string(bytes), nil -} diff --git a/template_test.go b/template_test.go index dc0c7ae0..0c4f0e64 100644 --- a/template_test.go +++ b/template_test.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "testing" @@ -16,32 +15,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestReadInput(t *testing.T) { - origfs := fs - defer func() { fs = origfs }() - fs = afero.NewMemMapFs() - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write([]byte("foo")) - - f, _ = fs.Create("/tmp/unreadable") - _, _ = f.Write([]byte("foo")) - - actual, err := readInput("/tmp/foo") - assert.NoError(t, err) - assert.Equal(t, "foo", actual) - - defer func() { stdin = os.Stdin }() - stdin = ioutil.NopCloser(bytes.NewBufferString("bar")) - - actual, err = readInput("-") - assert.NoError(t, err) - assert.Equal(t, "bar", actual) - - _, err = readInput("bogus") - assert.Error(t, err) -} - func TestOpenOutFile(t *testing.T) { origfs := fs defer func() { fs = origfs }() @@ -59,12 +32,11 @@ func TestOpenOutFile(t *testing.T) { assert.NoError(t, err) assert.Equal(t, config.NormalizeFileMode(0644), i.Mode()) - defer func() { Stdout = os.Stdout }() - Stdout = &iohelpers.NopCloser{Writer: &bytes.Buffer{}} + cfg.Stdout = &iohelpers.NopCloser{Writer: &bytes.Buffer{}} f, err = openOutFile(cfg, "-", 0644, false) assert.NoError(t, err) - assert.Equal(t, Stdout, f) + assert.Equal(t, cfg.Stdout, f) } func TestLoadContents(t *testing.T) { @@ -75,21 +47,9 @@ func TestLoadContents(t *testing.T) { afero.WriteFile(fs, "foo", []byte("contents"), 0644) tmpl := &tplate{name: "foo"} - err := tmpl.loadContents() - assert.NoError(t, err) - assert.Equal(t, "contents", tmpl.contents) -} - -func TestAddTarget(t *testing.T) { - origfs := fs - defer func() { fs = origfs }() - fs = afero.NewMemMapFs() - - cfg := &config.Config{} - tmpl := &tplate{name: "foo", targetPath: "/out/outfile"} - err := tmpl.addTarget(cfg) + b, err := tmpl.loadContents(nil) assert.NoError(t, err) - assert.NotNil(t, tmpl.target) + assert.Equal(t, "contents", string(b)) } func TestGatherTemplates(t *testing.T) { @@ -102,21 +62,25 @@ func TestGatherTemplates(t *testing.T) { afero.WriteFile(fs, "in/2", []byte("bar"), 0644) afero.WriteFile(fs, "in/3", []byte("baz"), 0644) - cfg := &config.Config{} + cfg := &config.Config{ + Stdin: &bytes.Buffer{}, + Stdout: &bytes.Buffer{}, + } cfg.ApplyDefaults() templates, err := gatherTemplates(cfg, nil) assert.NoError(t, err) assert.Len(t, templates, 1) cfg = &config.Config{ - Input: "foo", + Input: "foo", + Stdout: &iohelpers.NopCloser{Writer: &bytes.Buffer{}}, } cfg.ApplyDefaults() templates, err = gatherTemplates(cfg, nil) assert.NoError(t, err) assert.Len(t, templates, 1) assert.Equal(t, "foo", templates[0].contents) - assert.Equal(t, Stdout, templates[0].target) + assert.Equal(t, cfg.Stdout, templates[0].target) templates, err = gatherTemplates(&config.Config{ Input: "foo", @@ -140,14 +104,16 @@ func TestGatherTemplates(t *testing.T) { assert.Equal(t, config.NormalizeFileMode(0644), info.Mode()) fs.Remove("out") - templates, err = gatherTemplates(&config.Config{ + cfg = &config.Config{ InputFiles: []string{"foo"}, OutputFiles: []string{"out"}, - }, nil) + Stdout: &iohelpers.NopCloser{Writer: &bytes.Buffer{}}, + } + templates, err = gatherTemplates(cfg, nil) assert.NoError(t, err) assert.Len(t, templates, 1) assert.Equal(t, "bar", templates[0].contents) - assert.NotEqual(t, Stdout, templates[0].target) + assert.NotEqual(t, cfg.Stdout, templates[0].target) assert.Equal(t, os.FileMode(0600), templates[0].mode) _, err = templates[0].target.Write([]byte("hello world")) @@ -158,15 +124,17 @@ func TestGatherTemplates(t *testing.T) { assert.Equal(t, config.NormalizeFileMode(0600), info.Mode()) fs.Remove("out") - templates, err = gatherTemplates(&config.Config{ + cfg = &config.Config{ InputFiles: []string{"foo"}, OutputFiles: []string{"out"}, OutMode: "755", - }, nil) + Stdout: &iohelpers.NopCloser{Writer: &bytes.Buffer{}}, + } + templates, err = gatherTemplates(cfg, nil) assert.NoError(t, err) assert.Len(t, templates, 1) assert.Equal(t, "bar", templates[0].contents) - assert.NotEqual(t, Stdout, templates[0].target) + assert.NotEqual(t, cfg.Stdout, templates[0].target) assert.Equal(t, config.NormalizeFileMode(0755), templates[0].mode) _, err = templates[0].target.Write([]byte("hello world")) @@ -199,7 +167,9 @@ func TestProcessTemplates(t *testing.T) { afero.WriteFile(fs, "existing", []byte(""), config.NormalizeFileMode(0644)) - cfg := &config.Config{} + cfg := &config.Config{ + Stdout: &iohelpers.NopCloser{Writer: &bytes.Buffer{}}, + } testdata := []struct { templates []*tplate contents []string @@ -211,7 +181,7 @@ func TestProcessTemplates(t *testing.T) { templates: []*tplate{{name: "<arg>", contents: "foo", targetPath: "-", mode: 0644}}, contents: []string{"foo"}, modes: []os.FileMode{0644}, - targets: []io.WriteCloser{Stdout}, + targets: []io.WriteCloser{stdout(cfg)}, }, { templates: []*tplate{{name: "<arg>", contents: "foo", targetPath: "out", mode: 0644}}, @@ -265,8 +235,8 @@ func TestProcessTemplates(t *testing.T) { if len(in.targets) > 0 { assert.Equal(t, in.targets[i], a.target) } - if current.targetPath != "-" { - err = current.loadContents() + if current.targetPath != "-" && current.name != "<arg>" { + _, err = current.loadContents(nil) assert.NoError(t, err) n, err := current.target.Write([]byte("hello world")) |
