Skip to content

Commit

Permalink
Merge pull request #598 from urfave/backport-json-support
Browse files Browse the repository at this point in the history
Backport JSON InputSource to v1
  • Loading branch information
meatballhat committed Feb 26, 2018
2 parents d4bf9ce + 8dc47eb commit 8e01ec4
Show file tree
Hide file tree
Showing 3 changed files with 535 additions and 3 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -701,9 +701,9 @@ the yaml input source for any flags that are defined on that command. As a note
the "load" flag used would also have to be defined on the command flags in order
for this code snipped to work.

Currently only the aboved specified formats are supported but developers can
add support for other input sources by implementing the
altsrc.InputSourceContext for their given sources.
Currently only YAML and JSON files are supported but developers can add support
for other input sources by implementing the altsrc.InputSourceContext for their
given sources.

Here is a more complete sample of a command using YAML support:

Expand Down
324 changes: 324 additions & 0 deletions altsrc/json_command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,324 @@
package altsrc

import (
"flag"
"io/ioutil"
"os"
"testing"

"gopkg.in/urfave/cli.v1"
)

const (
fileName = "current.json"
simpleJSON = `{"test": 15}`
nestedJSON = `{"top": {"test": 15}}`
)

func TestCommandJSONFileTest(t *testing.T) {
cleanup := writeTempFile(t, fileName, simpleJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("test")
expect(t, val, 15)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))
err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileTestGlobalEnvVarWins(t *testing.T) {
cleanup := writeTempFile(t, fileName, simpleJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
os.Setenv("THE_TEST", "10")
defer os.Setenv("THE_TEST", "")

test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("test")
expect(t, val, 10)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "THE_TEST"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))

err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileTestGlobalEnvVarWinsNested(t *testing.T) {
cleanup := writeTempFile(t, fileName, nestedJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
os.Setenv("THE_TEST", "10")
defer os.Setenv("THE_TEST", "")

test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("top.test")
expect(t, val, 10)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))

err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileTestSpecifiedFlagWins(t *testing.T) {
cleanup := writeTempFile(t, fileName, simpleJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
test := []string{"test-cmd", "--load", fileName, "--test", "7"}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("test")
expect(t, val, 7)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))

err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileTestSpecifiedFlagWinsNested(t *testing.T) {
cleanup := writeTempFile(t, fileName, nestedJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
test := []string{"test-cmd", "--load", fileName, "--top.test", "7"}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("top.test")
expect(t, val, 7)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))

err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileTestDefaultValueFileWins(t *testing.T) {
cleanup := writeTempFile(t, fileName, simpleJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("test")
expect(t, val, 15)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test", Value: 7}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))

err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileTestDefaultValueFileWinsNested(t *testing.T) {
cleanup := writeTempFile(t, fileName, nestedJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("top.test")
expect(t, val, 15)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))

err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileFlagHasDefaultGlobalEnvJSONSetGlobalEnvWins(t *testing.T) {
cleanup := writeTempFile(t, fileName, simpleJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
os.Setenv("THE_TEST", "11")
defer os.Setenv("THE_TEST", "")

test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("test")
expect(t, val, 11)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVar: "THE_TEST"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))
err := command.Run(c)

expect(t, err, nil)
}

func TestCommandJSONFileFlagHasDefaultGlobalEnvJSONSetGlobalEnvWinsNested(t *testing.T) {
cleanup := writeTempFile(t, fileName, nestedJSON)
defer cleanup()

app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
os.Setenv("THE_TEST", "11")
defer os.Setenv("THE_TEST", "")

test := []string{"test-cmd", "--load", fileName}
set.Parse(test)

c := cli.NewContext(app, set, nil)

command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
val := c.Int("top.test")
expect(t, val, 11)
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}),
&cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewJSONSourceFromFlagFunc("load"))
err := command.Run(c)

expect(t, err, nil)
}

func writeTempFile(t *testing.T, name string, content string) func() {
if err := ioutil.WriteFile(name, []byte(content), 0666); err != nil {
t.Fatalf("cannot write %q: %v", name, err)
}
return func() {
if err := os.Remove(name); err != nil {
t.Errorf("cannot remove %q: %v", name, err)
}
}
}

0 comments on commit 8e01ec4

Please sign in to comment.