command/fmt: Accept input from STDIN

So that you can do automatic formatting from an editor. You probably want to
disable the `-write` and `-list` options so that you just get the
re-formatted content, e.g.

    cat main.tf | terraform fmt -write=false -list=false -

I've added a non-exported field called `input` so that we can override this
for the tests. If not specified, like in `commands.go`, then it will default
to `os.Stdin` which works on the command line.
This commit is contained in:
Dan Carley 2016-02-02 22:10:22 +00:00
parent 1b967e612f
commit e9128769b5
3 changed files with 46 additions and 7 deletions

View File

@ -3,6 +3,8 @@ package command
import ( import (
"flag" "flag"
"fmt" "fmt"
"io"
"os"
"strings" "strings"
"github.com/hashicorp/hcl/hcl/fmtcmd" "github.com/hashicorp/hcl/hcl/fmtcmd"
@ -10,6 +12,7 @@ import (
) )
const ( const (
stdinArg = "-"
fileExtension = "tf" fileExtension = "tf"
) )
@ -18,9 +21,14 @@ const (
type FmtCommand struct { type FmtCommand struct {
Meta Meta
opts fmtcmd.Options opts fmtcmd.Options
input io.Reader // STDIN if nil
} }
func (c *FmtCommand) Run(args []string) int { func (c *FmtCommand) Run(args []string) int {
if c.input == nil {
c.input = os.Stdin
}
args = c.Meta.process(args, false) args = c.Meta.process(args, false)
cmdFlags := flag.NewFlagSet("fmt", flag.ContinueOnError) cmdFlags := flag.NewFlagSet("fmt", flag.ContinueOnError)
@ -40,15 +48,15 @@ func (c *FmtCommand) Run(args []string) int {
return 1 return 1
} }
var dir string var dirs []string
if len(args) == 0 { if len(args) == 0 {
dir = "." dirs = []string{"."}
} else { } else if args[0] != stdinArg {
dir = args[0] dirs = []string{args[0]}
} }
output := &cli.UiWriter{Ui: c.Ui} output := &cli.UiWriter{Ui: c.Ui}
err := fmtcmd.Run([]string{dir}, []string{fileExtension}, nil, output, c.opts) err := fmtcmd.Run(dirs, []string{fileExtension}, c.input, output, c.opts)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err)) c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err))
return 2 return 2
@ -64,6 +72,7 @@ Usage: terraform fmt [options] [DIR]
Rewrites all Terraform configuration files to a canonical format. Rewrites all Terraform configuration files to a canonical format.
If DIR is not specified then the current working directory will be used. If DIR is not specified then the current working directory will be used.
If DIR is "-" then content will be read from STDIN.
Options: Options:

View File

@ -1,6 +1,7 @@
package command package command
import ( import (
"bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -123,6 +124,34 @@ func TestFmt_directoryArg(t *testing.T) {
} }
} }
func TestFmt_stdinArg(t *testing.T) {
input := new(bytes.Buffer)
input.Write(fmtFixture.input)
ui := new(cli.MockUi)
c := &FmtCommand{
Meta: Meta{
ContextOpts: testCtxConfig(testProvider()),
Ui: ui,
},
input: input,
}
args := []string{
"-write=false",
"-list=false",
"-",
}
if code := c.Run(args); code != 0 {
t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
}
expected := fmtFixture.golden
if actual := ui.OutputWriter.Bytes(); !bytes.Equal(actual, expected) {
t.Fatalf("got: %q\nexpected: %q", actual, expected)
}
}
var fmtFixture = struct { var fmtFixture = struct {
filename string filename string
input, golden []byte input, golden []byte

View File

@ -17,7 +17,8 @@ Usage: `terraform fmt [options] [DIR]`
By default, `fmt` scans the current directory for configuration files. If By default, `fmt` scans the current directory for configuration files. If
the `dir` argument is provided then it will scan that given directory the `dir` argument is provided then it will scan that given directory
instead. instead. If `dir` is a single dash (`-`) then `fmt` will read from standard
input (STDIN).
The command-line flags are all optional. The list of available flags are: The command-line flags are all optional. The list of available flags are: