diff --git a/cmd/diff.go b/cmd/diff.go index 26fdf83f4..cc12e0cdf 100644 --- a/cmd/diff.go +++ b/cmd/diff.go @@ -56,7 +56,8 @@ that will be created or updated or deleted. func init() { rootCmd.AddCommand(diffCmd) diffCmd.Flags().StringVarP(&diffCmdKongStateFile, - "state", "s", "kong.yaml", "file containing Kong's configuration.") + "state", "s", "kong.yaml", "file containing Kong's configuration. "+ + "Use '-' to read from stdin.") diffCmd.Flags().BoolVar(&dumpConfig.SkipConsumers, "skip-consumers", false, "do not diff consumers or "+ "any plugins associated with consumers") diff --git a/cmd/sync.go b/cmd/sync.go index 00a649399..ad3068727 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -53,7 +53,8 @@ to get Kong's state in sync with the input state.`, func init() { rootCmd.AddCommand(syncCmd) syncCmd.Flags().StringVarP(&syncCmdKongStateFile, - "state", "s", "kong.yaml", "file containing Kong's configuration.") + "state", "s", "kong.yaml", "file containing Kong's configuration. "+ + "Use '-' to read from stdin.") syncCmd.Flags().BoolVar(&dumpConfig.SkipConsumers, "skip-consumers", false, "do not diff consumers or "+ "any plugins associated with consumers") diff --git a/file/reader.go b/file/reader.go index 03d11baf4..710e1ad0a 100644 --- a/file/reader.go +++ b/file/reader.go @@ -3,6 +3,7 @@ package file import ( "fmt" "io/ioutil" + "os" "strconv" "github.com/hbagdi/deck/counter" @@ -223,7 +224,13 @@ func GetStateFromFile(filename string) (*state.KongState, error) { func readFile(kongStateFile string) (*fileStructure, error) { var s fileStructure - b, err := ioutil.ReadFile(kongStateFile) + var b []byte + var err error + if kongStateFile == "-" { + b, err = ioutil.ReadAll(os.Stdin) + } else { + b, err = ioutil.ReadFile(kongStateFile) + } if err != nil { return nil, err } diff --git a/file/reader_test.go b/file/reader_test.go index 60241bf38..54fff77af 100644 --- a/file/reader_test.go +++ b/file/reader_test.go @@ -1,8 +1,13 @@ package file import ( + "bytes" + "io/ioutil" + "os" "reflect" "testing" + + "github.com/stretchr/testify/assert" ) func Test_ensureJSON(t *testing.T) { @@ -32,3 +37,76 @@ func Test_ensureJSON(t *testing.T) { }) } } + +func TestReadKongStateFromStdinFailsToParseText(t *testing.T) { + var filename = "-" + assert := assert.New(t) + assert.Equal("-", filename) + + var content bytes.Buffer + content.Write([]byte("hunter2\n")) + + tmpfile, err := ioutil.TempFile("", "example") + if err != nil { + panic(err) + } + defer os.Remove(tmpfile.Name()) + + if _, err := tmpfile.Write(content.Bytes()); err != nil { + panic(err) + } + + if _, err := tmpfile.Seek(0, 0); err != nil { + panic(err) + } + + oldStdin := os.Stdin + defer func() { os.Stdin = oldStdin }() // Restore original Stdin + + os.Stdin = tmpfile + + ks, err := GetStateFromFile(filename) + assert.NotNil(err) + assert.Nil(ks) +} + +func TestReadKongStateFromStdin(t *testing.T) { + var filename = "-" + assert := assert.New(t) + assert.Equal("-", filename) + + var content bytes.Buffer + content.Write([]byte("services:\n- host: test.com\n name: test service\n")) + + tmpfile, err := ioutil.TempFile("", "example") + if err != nil { + panic(err) + } + defer os.Remove(tmpfile.Name()) + + if _, err := tmpfile.Write(content.Bytes()); err != nil { + panic(err) + } + + if _, err := tmpfile.Seek(0, 0); err != nil { + panic(err) + } + + oldStdin := os.Stdin + defer func() { os.Stdin = oldStdin }() // Restore original Stdin + + os.Stdin = tmpfile + + ks, err := GetStateFromFile(filename) + assert.NotNil(ks) + assert.Nil(err) + + services, err := ks.Services.GetAll() + if err != nil { + panic(err) + } + assert.Equal("test.com", *services[0].Host) + assert.NotEqual("not.the.same.as.test.com", *services[0].Host) + assert.Equal("test service", *services[0].Name) + assert.NotEqual("not the same as 'test service'", *services[0].Name) +}