feat(kit/cli): add support for int32 and int64 CLI flags

pull/20109/head
Dan Moran 2020-11-24 10:13:50 -05:00 committed by Daniel Moran
parent affb64c888
commit a952dff92d
2 changed files with 85 additions and 2 deletions

View File

@ -150,6 +150,58 @@ func BindOptions(v *viper.Viper, cmd *cobra.Command, opts []Opt) {
}
mustBindPFlag(v, o.Flag, flagset)
*destP = v.GetInt(envVar)
case *int32:
var d int32
if o.Default != nil {
// N.B. since our CLI kit types default values as interface{} and
// literal numbers get typed as int by default, it's very easy to
// create an int32 CLI flag with an int default value.
//
// The compiler doesn't know to complain in that case, so you end up
// with a runtime panic when trying to bind the CLI options.
//
// To avoid that headache, we support both int32 and int defaults
// for int32 fields. This introduces a new runtime bomb if somebody
// specifies an int default > math.MaxInt32, but that's hopefully
// less likely.
var ok bool
d, ok = o.Default.(int32)
if !ok {
d = int32(o.Default.(int))
}
}
if hasShort {
flagset.Int32VarP(destP, o.Flag, string(o.Short), d, o.Desc)
} else {
flagset.Int32Var(destP, o.Flag, d, o.Desc)
}
mustBindPFlag(v, o.Flag, flagset)
*destP = v.GetInt32(envVar)
case *int64:
var d int64
if o.Default != nil {
// N.B. since our CLI kit types default values as interface{} and
// literal numbers get typed as int by default, it's very easy to
// create an int64 CLI flag with an int default value.
//
// The compiler doesn't know to complain in that case, so you end up
// with a runtime panic when trying to bind the CLI options.
//
// To avoid that headache, we support both int64 and int defaults
// for int64 fields.
var ok bool
d, ok = o.Default.(int64)
if !ok {
d = int64(o.Default.(int))
}
}
if hasShort {
flagset.Int64VarP(destP, o.Flag, string(o.Short), d, o.Desc)
} else {
flagset.Int64Var(destP, o.Flag, d, o.Desc)
}
mustBindPFlag(v, o.Flag, flagset)
*destP = v.GetInt64(envVar)
case *bool:
var d bool
if o.Default != nil {

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"math"
"os"
"path"
"testing"
@ -40,6 +41,8 @@ func (c *customFlag) Type() string {
func ExampleNewCommand() {
var monitorHost string
var number int
var smallerNumber int32
var longerNumber int64
var sleep bool
var duration time.Duration
var stringSlice []string
@ -50,6 +53,7 @@ func ExampleNewCommand() {
for i := 0; i < number; i++ {
fmt.Printf("%d\n", i)
}
fmt.Println(longerNumber - int64(smallerNumber))
fmt.Println(sleep)
fmt.Println(duration)
fmt.Println(stringSlice)
@ -70,6 +74,18 @@ func ExampleNewCommand() {
Default: 2,
Desc: "number of times to loop",
},
{
DestP: &smallerNumber,
Flag: "smaller-number",
Default: math.MaxInt32,
Desc: "limited size number",
},
{
DestP: &longerNumber,
Flag: "longer-number",
Default: math.MaxInt64,
Desc: "explicitly expanded-size number",
},
{
DestP: &sleep,
Flag: "sleep",
@ -104,6 +120,7 @@ func ExampleNewCommand() {
// http://localhost:8086
// 0
// 1
// 9223372034707292160
// true
// 1m0s
// [foo bar]
@ -113,8 +130,10 @@ func ExampleNewCommand() {
func Test_NewProgram(t *testing.T) {
testFilePath, cleanup := newConfigFile(t, map[string]string{
// config values should be same as flags
"foo": "bar",
"shoe-fly": "yadon",
"foo": "bar",
"shoe-fly": "yadon",
"number": "2147483647",
"long-number": "9223372036854775807",
})
defer cleanup()
defer setEnvVar("TEST_CONFIG_PATH", testFilePath)()
@ -155,6 +174,8 @@ func Test_NewProgram(t *testing.T) {
var testVar string
var testFly string
var testNumber int32
var testLongNumber int64
program := &Program{
Name: "test",
Opts: []Opt{
@ -167,6 +188,14 @@ func Test_NewProgram(t *testing.T) {
DestP: &testFly,
Flag: "shoe-fly",
},
{
DestP: &testNumber,
Flag: "number",
},
{
DestP: &testLongNumber,
Flag: "long-number",
},
},
Run: func() error { return nil },
}
@ -177,6 +206,8 @@ func Test_NewProgram(t *testing.T) {
require.Equal(t, tt.expected, testVar)
assert.Equal(t, "yadon", testFly)
assert.Equal(t, int32(math.MaxInt32), testNumber)
assert.Equal(t, int64(math.MaxInt64), testLongNumber)
}
t.Run(tt.name, fn)