Skip to content

Commit 7320050

Browse files
authored
Merge pull request #2 from awslabs/stdin-support
Stdin support
2 parents f4e4a9b + 993be22 commit 7320050

File tree

4 files changed

+72
-39
lines changed

4 files changed

+72
-39
lines changed

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ To use `cfn-format`, you can clone this repository and run `go build` or downloa
1515
### Command-line tool
1616

1717
```console
18-
Usage: cfn-format [-j] <filename>
18+
Usage: cfn-format [OPTION...] [FILENAME]
1919

2020
AWS CloudFormation Format is a tool that reads a CloudFormation template
2121
and outputs the same template, formatted according to the same standards
2222
used in AWS documentation.
2323

24+
If FILENAME is not supplied, cfn-format will read from STDIN.
25+
2426
Options:
25-
-j Output the template as JSON (default format: YAML).
26-
-w Write the output back to the file rather than to stdout.
2727
--help Show this message and exit.
28+
-j, --json Output the template as JSON (default format: YAML).
29+
-w, --write Write the output back to the file rather than to stdout.
2830
```
2931

3032
### Go package documentation

main.go

+45-36
Original file line numberDiff line numberDiff line change
@@ -7,64 +7,73 @@ import (
77

88
"github.com/awslabs/aws-cloudformation-template-formatter/format"
99
"github.com/awslabs/aws-cloudformation-template-formatter/parse"
10+
11+
"github.com/andrew-d/go-termutil"
12+
"github.com/spf13/pflag"
1013
)
1114

12-
var usage = `Usage: cfn-format [-j] <filename>
15+
var usage = `Usage: cfn-format [OPTION...] [FILENAME]
1316
1417
AWS CloudFormation Format is a tool that reads a CloudFormation template
1518
and outputs the same template, formatted according to the same standards
1619
used in AWS documentation.
1720
21+
If FILENAME is not supplied, cfn-format will read from STDIN.
22+
1823
Options:
19-
-j Output the template as JSON (default format: YAML).
20-
-w Write the output back to the file rather than to stdout.
21-
--help Show this message and exit.
22-
`
24+
--help Show this message and exit.`
25+
26+
var jsonFlag bool
27+
var writeFlag bool
28+
29+
func init() {
30+
pflag.BoolVarP(&jsonFlag, "json", "j", false, "Output the template as JSON (default format: YAML).")
31+
pflag.BoolVarP(&writeFlag, "write", "w", false, "Write the output back to the file rather than to stdout.")
32+
33+
pflag.Usage = func() {
34+
fmt.Fprintln(os.Stderr, usage)
35+
pflag.PrintDefaults()
36+
os.Exit(1)
37+
}
38+
}
2339

2440
func die(message string) {
2541
fmt.Fprintln(os.Stderr, message)
2642
os.Exit(1)
2743
}
2844

29-
func help() {
30-
die(usage)
31-
}
32-
3345
func main() {
34-
style := "yaml"
35-
write := false
46+
var fileName string
47+
var source map[string]interface{}
48+
var err error
3649

37-
// Parse options
38-
if len(os.Args) < 2 {
39-
help()
40-
}
50+
pflag.Parse()
51+
args := pflag.Args()
4152

42-
for _, arg := range os.Args[1 : len(os.Args)-1] {
43-
switch arg {
44-
case "-j":
45-
style = "json"
46-
case "-w":
47-
write = true
48-
case "-h", "--help":
49-
help()
53+
if len(args) == 1 {
54+
// Reading from a file
55+
fileName = args[0]
56+
source, err = parse.ReadFile(fileName)
57+
if err != nil {
58+
die(err.Error())
59+
}
60+
} else if !termutil.Isatty(os.Stdin.Fd()) {
61+
if writeFlag {
62+
// Can't use write without a filename!
63+
die("Can't write back to a file when reading from stdin")
5064
}
51-
}
52-
53-
// Get the filename
54-
fileName := os.Args[len(os.Args)-1]
55-
if fileName == "--help" {
56-
help()
57-
}
5865

59-
// Read the source template
60-
source, err := parse.ReadFile(fileName)
61-
if err != nil {
62-
die(err.Error())
66+
source, err = parse.Read(os.Stdin)
67+
if err != nil {
68+
die(err.Error())
69+
}
70+
} else {
71+
pflag.Usage()
6372
}
6473

6574
// Format the output
6675
var output string
67-
if style == "json" {
76+
if jsonFlag {
6877
output = format.Json(source)
6978
} else {
7079
output = format.Yaml(source)
@@ -76,7 +85,7 @@ func main() {
7685
die(err.Error())
7786
}
7887

79-
if write {
88+
if writeFlag {
8089
ioutil.WriteFile(fileName, []byte(output), 0644)
8190
} else {
8291
fmt.Println(output)

parse/parse.go

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package parse
33
import (
44
"encoding/json"
55
"fmt"
6+
"io"
67
"io/ioutil"
78
"reflect"
89

@@ -56,6 +57,15 @@ func (t *tagUnmarshalerType) UnmarshalYAMLTag(tag string, value reflect.Value) r
5657
return output
5758
}
5859

60+
func Read(r io.Reader) (map[string]interface{}, error) {
61+
data, err := ioutil.ReadAll(r)
62+
if err != nil {
63+
return nil, fmt.Errorf("Unable to read input: %s", err)
64+
}
65+
66+
return ReadString(string(data))
67+
}
68+
5969
func ReadFile(fileName string) (map[string]interface{}, error) {
6070
source, err := ioutil.ReadFile(fileName)
6171
if err != nil {

parse/parse_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package parse
22

33
import (
44
"io/ioutil"
5+
"strings"
56
"testing"
67

78
"github.com/google/go-cmp/cmp"
@@ -45,6 +46,17 @@ func init() {
4546
testTemplate = string(data)
4647
}
4748

49+
func TestRead(t *testing.T) {
50+
actual, err := Read(strings.NewReader(testTemplate))
51+
if err != nil {
52+
t.Error(err)
53+
}
54+
55+
if diff := cmp.Diff(actual, expected); diff != "" {
56+
t.Errorf(diff)
57+
}
58+
}
59+
4860
func TestReadFile(t *testing.T) {
4961
actual, err := ReadFile(testFile)
5062
if err != nil {

0 commit comments

Comments
 (0)