Skip to content

Commit

Permalink
[CLI] Set service name dynamically if not provided (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
eculver authored Apr 11, 2017
1 parent e053bc7 commit 85a99ba
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 109 deletions.
4 changes: 2 additions & 2 deletions cmd/dosa/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type GlobalOptions struct {
Host string `long:"host" default:"127.0.0.1" description:"The hostname or IP for the gateway."`
Port string `short:"p" long:"port" default:"21300" description:"The hostname or IP for the gateway."`
Transport string `long:"transport" default:"tchannel" description:"TCP Transport to use. Options: http, tchannel."`
ServiceName string `long:"service" default:"dosa-gateway" description:"The TChannel service name for the gateway."`
ServiceName string `long:"service" description:"The TChannel service name for the gateway."`
CallerName string `long:"caller" default:"dosacli-$USER" description:"Caller will override the default caller name (which is dosacli-$USER)."`
Timeout timeFlag `long:"timeout" default:"60s" description:"The timeout for gateway requests. E.g., 100ms, 0.5s, 1s. If no unit is specified, milliseconds are assumed."`
Connector string `hidden:"true" long:"connector" default:"yarpc" description:"Name of connector to use"`
Expand All @@ -53,7 +53,7 @@ func main() {
OptionsParser.ShortDescription = "DOSA CLI - The command-line tool for your DOSA client"
OptionsParser.LongDescription = `
dosa manages your schema both in production and development scopes`
c, _ := OptionsParser.AddCommand("scope", "commands to manage scope", "create, drop, or truncate development scopes", &ScopeCmd{})
c, _ := OptionsParser.AddCommand("scope", "commands to manage scope", "create, drop, or truncate development scopes", &ScopeOptions{})
_, _ = c.AddCommand("create", "Create scope", "creates a new scope", &ScopeCreate{})
_, _ = c.AddCommand("drop", "Drop scope", "drops a scope", &ScopeDrop{})
_, _ = c.AddCommand("truncate", "Truncate scope", "truncates a scope", &ScopeTruncate{})
Expand Down
6 changes: 6 additions & 0 deletions cmd/dosa/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ import (
"github.com/uber-go/dosa"
)

const (
_defServiceName = "dosa-dev-gateway"
_prodServiceName = "dosa-gateway"
_prodScope = "production"
)

type timeFlag time.Duration

func (t *timeFlag) setDuration(d time.Duration) {
Expand Down
26 changes: 22 additions & 4 deletions cmd/dosa/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ func (c *SchemaCmd) doSchemaOp(name string, f func(dosa.AdminClient, context.Con
fmt.Printf("options are %+v\n", *c)
fmt.Printf("global options are %+v\n", options)
}

// if not given, set the service name dynamically based on scope
if options.ServiceName == "" {
options.ServiceName = _defServiceName
if c.Scope == _prodScope {
options.ServiceName = _prodServiceName
}
}

client, err := getAdminClient(options)
if err != nil {
return err
Expand Down Expand Up @@ -99,27 +108,36 @@ func (c *SchemaCmd) doSchemaOp(name string, f func(dosa.AdminClient, context.Con
// SchemaCheck holds the options for 'schema check'
type SchemaCheck struct {
*SchemaCmd
Args struct {
Paths []string `positional-arg-name:"paths"`
} `positional-args:"yes"`
}

// Execute executes a schema check command
func (c *SchemaCheck) Execute(args []string) error {
return c.doSchemaOp("schema check", dosa.AdminClient.CheckSchema, args)
return c.doSchemaOp("schema check", dosa.AdminClient.CheckSchema, c.Args.Paths)
}

// SchemaUpsert contains data for executing schema upsert command.
type SchemaUpsert struct {
*SchemaCmd
Args struct {
Paths []string `positional-arg-name:"paths"`
} `positional-args:"yes"`
}

// Execute executes a schema upsert command
func (c *SchemaUpsert) Execute(args []string) error {
return c.doSchemaOp("schema upsert", dosa.AdminClient.UpsertSchema, args)
return c.doSchemaOp("schema upsert", dosa.AdminClient.UpsertSchema, c.Args.Paths)
}

// SchemaDump contains data for executing the schema dump command
type SchemaDump struct {
*SchemaOptions
Format string `long:"format" short:"f" description:"output format" choice:"cql" choice:"uql" choice:"avro" default:"cql"`
Args struct {
Paths []string `positional-arg-name:"paths"`
} `positional-args:"yes"`
}

// Execute executes a schema dump command
Expand All @@ -132,8 +150,8 @@ func (c *SchemaDump) Execute(args []string) error {

// no connection necessary
client := dosa.NewAdminClient(&devnull.Connector{})
if len(args) != 0 {
dirs, err := expandDirectories(args)
if len(c.Args.Paths) != 0 {
dirs, err := expandDirectories(c.Args.Paths)
if err != nil {
return errors.Wrap(err, "could not expand directories")
}
Expand Down
191 changes: 128 additions & 63 deletions cmd/dosa/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/uber-go/dosa"
"github.com/uber-go/dosa/mocks"

_ "github.com/uber-go/dosa/connectors/devnull"
)

func TestSchema_ExpandDirectories(t *testing.T) {
Expand Down Expand Up @@ -90,76 +92,131 @@ func TestSchema_ExpandDirectories(t *testing.T) {
os.Chdir("..")
}

func TestSchema_Check_PrefixRequired(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "check", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "--prefix' was not specified")
}

func TestSchema_Upsert_PrefixRequired(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "upsert", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "--prefix' was not specified")
}

func TestSchema_Check_InvalidDirectory(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "check", "--prefix", "foo", "../../testentity", "/dev/null"}
main()
assert.Contains(t, c.stop(true), "\"/dev/null\" is not a directory")
}

func TestSchema_Upsert_InvalidDirectory(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "upsert", "--prefix", "foo", "../../testentity", "/dev/null"}
main()
assert.Contains(t, c.stop(true), "\"/dev/null\" is not a directory")
}

func TestSchema_Dump_InvalidDirectory(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "dump", "../../testentity", "/dev/null"}
main()
assert.Contains(t, c.stop(true), "\"/dev/null\" is not a directory")
}
func TestSchema_ServiceInference(t *testing.T) {
tcs := []struct {
serviceName string
scope string
expected string
}{
// service = "", scope = "" -> default
{
expected: _defServiceName,
},
// service = "", scope != prod -> default
{
scope: "not-production",
expected: _defServiceName,
},
// service = "", scope = prod -> prod
{
scope: _prodScope,
expected: _prodServiceName,
},
// service = "foo", scope = "" -> "foo"
{
serviceName: "foo",
expected: "foo",
},
// service = "bar", scope != prod -> "bar"
{
serviceName: "bar",
scope: "bar",
expected: "bar",
},
// service = "baz", scope = prod -> "baz"
{
serviceName: "baz",
scope: _prodScope,
expected: "baz",
},
}

func TestSchema_Check_NoEntitiesFound(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "check", "--prefix", "foo", "-e", "testentity.go", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "no entities found")
for _, tc := range tcs {
for _, cmd := range []string{"check", "upsert"} {
os.Args = []string{
"dosa",
"--service", tc.serviceName,
"--connector", "devnull",
"schema",
cmd,
"--prefix", "foo",
"--scope", tc.scope,
"../../testentity",
}
main()
assert.Equal(t, options.ServiceName, tc.expected)
}
}
}

func TestSchema_Upsert_NoEntitiesFound(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "upsert", "--prefix", "foo", "-e", "testentity.go", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "no entities found")
func TestSchema_PrefixRequired(t *testing.T) {
for _, cmd := range []string{"check", "upsert"} {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{
"dosa",
"schema",
cmd,
"../../testentity",
}
main()
assert.Contains(t, c.stop(true), "--prefix' was not specified")
}
}

func TestSchema_Dump_NoEntitiesFound(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "dump", "-e", "testentity.go", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "no entities found")
func TestSchema_InvalidDirectory(t *testing.T) {
// dump is a special snowflake
prefixMap := map[string]bool{
"check": true,
"upsert": true,
"dump": false,
}
for cmd, hasPrefix := range prefixMap {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{
"dosa",
"schema",
cmd,
}
if hasPrefix {
os.Args = append(os.Args, "--prefix", "foo")
}
os.Args = append(os.Args, []string{
"-e", "testentity.go",
"../../testentity",
"/dev/null",
}...)
main()
assert.Contains(t, c.stop(true), "\"/dev/null\" is not a directory")
}
}

func TestSchema_Dump_InvalidFormat(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "dump", "-f", "invalid", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "Invalid value")
func TestSchema_NoEntitiesFound(t *testing.T) {
// dump is a special snowflake
prefixMap := map[string]bool{
"check": true,
"upsert": true,
"dump": false,
}
for cmd, hasPrefix := range prefixMap {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{
"dosa",
"schema",
cmd,
}
if hasPrefix {
os.Args = append(os.Args, "--prefix", "foo")
}
os.Args = append(os.Args, []string{
"-e", "testentity.go",
"../../testentity",
}...)
main()
assert.Contains(t, c.stop(true), "no entities found")
}
}

// There are 4 tests to perform against each operation
Expand Down Expand Up @@ -214,6 +271,14 @@ func TestSchema_Upsert_Happy(t *testing.T) {
main()
}

func TestSchema_Dump_InvalidFormat(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
os.Args = []string{"dosa", "schema", "dump", "-f", "invalid", "../../testentity"}
main()
assert.Contains(t, c.stop(true), "Invalid value")
}

func TestSchema_Dump_CQL(t *testing.T) {
c := StartCapture()
exit = func(r int) {}
Expand Down
Loading

0 comments on commit 85a99ba

Please sign in to comment.