From fd1a616a6c2ab167f123a1c5d80353ceb23ba1ad Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Tue, 18 May 2021 10:03:58 -0700 Subject: [PATCH] Support binding pflags to default variable fields (#69) * Update CI post migration (#68) * Update CI post migration * Migrate to github workflows * length check * debug * Avoid installing pflags from repo * Update deps * update go action * try import path * update protos * set checkout depth * cleanup * typo in master wf Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Disable scoope publishing Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Rename (#73) * first pass at updating references * update module name * update boilerplate mod * remove version * mor * mockery * maybe * mor * replace replace * trying something * other Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Remove dependency on lyft/api (#71) Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Always try to create a bucket when loading a container (#76) Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Update create container if not exists logic (#77) Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Support binding pflags to default variable fields Support Map Types now that viper does Signed-off-by: Haytham Abuelfutuh Signed-off-by: Prafulla Mahindrakar * Added some coverage Signed-off-by: Prafulla Mahindrakar * Reverting to go 1.16 Signed-off-by: Prafulla Mahindrakar * Fixed unit test Signed-off-by: Prafulla Mahindrakar * Added more coverage Signed-off-by: Prafulla Mahindrakar Co-authored-by: brucearctor <5032356+brucearctor@users.noreply.github.com> Co-authored-by: Ketan Umare <16888709+kumare3@users.noreply.github.com> Co-authored-by: Katrina Rogan Co-authored-by: Prafulla Mahindrakar --- cli/pflags/api/generator.go | 166 ++++++++++++++------ cli/pflags/api/generator_test.go | 91 ++++++++++- cli/pflags/api/sample.go | 1 + cli/pflags/api/templates.go | 23 ++- cli/pflags/api/testdata/testtype.go | 12 +- cli/pflags/api/testdata/testtype_test.go | 190 +++-------------------- cli/pflags/api/types.go | 20 +-- cli/pflags/api/utils.go | 4 + cli/pflags/cmd/root.go | 8 +- go.mod | 1 - go.sum | 23 ++- 11 files changed, 297 insertions(+), 242 deletions(-) diff --git a/cli/pflags/api/generator.go b/cli/pflags/api/generator.go index 0fca81c..2917e58 100644 --- a/cli/pflags/api/generator.go +++ b/cli/pflags/api/generator.go @@ -20,9 +20,10 @@ const ( // PFlagProviderGenerator parses and generates GetPFlagSet implementation to add PFlags for a given struct's fields. type PFlagProviderGenerator struct { - pkg *types.Package - st *types.Named - defaultVar *types.Var + pkg *types.Package + st *types.Named + defaultVar *types.Var + shouldBindDefaultVar bool } // This list is restricted because that's the only kinds viper parses out, otherwise it assumes strings. @@ -35,6 +36,7 @@ var allowedKinds = []types.Type{ types.Typ[types.Int64], types.Typ[types.Bool], types.Typ[types.String], + types.NewMap(types.Typ[types.String], types.Typ[types.String]), } type SliceOrArray interface { @@ -49,8 +51,8 @@ func capitalize(s string) string { return s } -func buildFieldForSlice(ctx context.Context, t SliceOrArray, name, goName, usage, defaultValue string) (FieldInfo, error) { - strategy := SliceRaw +func buildFieldForSlice(ctx context.Context, t SliceOrArray, name, goName, usage, defaultValue string, bindDefaultVar bool) (FieldInfo, error) { + strategy := Raw FlagMethodName := "StringSlice" typ := types.NewSlice(types.Typ[types.String]) emptyDefaultValue := `[]string{}` @@ -76,14 +78,59 @@ func buildFieldForSlice(ctx context.Context, t SliceOrArray, name, goName, usage } return FieldInfo{ - Name: name, - GoName: goName, - Typ: typ, - FlagMethodName: FlagMethodName, - DefaultValue: defaultValue, - UsageString: usage, - TestValue: testValue, - TestStrategy: strategy, + Name: name, + GoName: goName, + Typ: typ, + FlagMethodName: FlagMethodName, + DefaultValue: defaultValue, + UsageString: usage, + TestValue: testValue, + TestStrategy: strategy, + ShouldBindDefault: bindDefaultVar, + }, nil +} + +func buildFieldForMap(ctx context.Context, t *types.Map, name, goName, usage, defaultValue string, bindDefaultVar bool) (FieldInfo, error) { + strategy := Raw + FlagMethodName := "StringToString" + typ := types.NewMap(types.Typ[types.String], types.Typ[types.String]) + emptyDefaultValue := `nil` + if k, ok := t.Key().(*types.Basic); !ok || k.Kind() != types.String { + logger.Infof(ctx, "Key of type [%v] is not a basic type. It must be json unmarshalable or generation will fail.", t.Elem()) + } else if v, valueOk := t.Elem().(*types.Basic); !valueOk && !isJSONUnmarshaler(t.Elem()) { + return FieldInfo{}, + fmt.Errorf("map of type [%v] is not supported. Only basic slices or slices of json-unmarshalable types are supported", + t.Elem().String()) + } else { + logger.Infof(ctx, "Map[%v]%v is supported. using pflag maps.", k, t.Elem()) + strategy = Raw + if valueOk { + FlagMethodName = fmt.Sprintf("StringTo%v", capitalize(v.Name())) + typ = types.NewMap(k, v) + emptyDefaultValue = fmt.Sprintf(`map[%v]%v{}`, k.Name(), v.Name()) + } else { + // Value is not a basic type. Rely on json marshaling to unmarshal it + FlagMethodName = fmt.Sprintf("StringToString") + } + } + + if len(defaultValue) == 0 { + defaultValue = emptyDefaultValue + } + + testValue := `"a=1,b=2"` + + return FieldInfo{ + Name: name, + GoName: goName, + Typ: typ, + FlagMethodName: FlagMethodName, + DefaultValue: defaultValue, + UsageString: usage, + TestValue: testValue, + TestStrategy: strategy, + ShouldBindDefault: bindDefaultVar, + ShouldTestDefault: false, }, nil } @@ -121,7 +168,7 @@ func appendAccessors(accessors ...string) string { // met; encountered a basic type (e.g. string, int... etc.) or the field type implements UnmarshalJSON. // If passed a non-empty defaultValueAccessor, it'll be used to fill in default values instead of any default value // specified in pflag tag. -func discoverFieldsRecursive(ctx context.Context, typ *types.Named, defaultValueAccessor, fieldPath string) ([]FieldInfo, error) { +func discoverFieldsRecursive(ctx context.Context, typ *types.Named, defaultValueAccessor, fieldPath string, bindDefaultVar bool) ([]FieldInfo, error) { logger.Printf(ctx, "Finding all fields in [%v.%v.%v]", typ.Obj().Pkg().Path(), typ.Obj().Pkg().Name(), typ.Obj().Name()) @@ -187,14 +234,15 @@ func discoverFieldsRecursive(ctx context.Context, typ *types.Named, defaultValue } fields = append(fields, FieldInfo{ - Name: tag.Name, - GoName: v.Name(), - Typ: t, - FlagMethodName: camelCase(t.String()), - DefaultValue: defaultValue, - UsageString: tag.Usage, - TestValue: `"1"`, - TestStrategy: JSON, + Name: tag.Name, + GoName: v.Name(), + Typ: t, + FlagMethodName: camelCase(t.String()), + DefaultValue: defaultValue, + UsageString: tag.Usage, + TestValue: `"1"`, + TestStrategy: JSON, + ShouldBindDefault: bindDefaultVar, }) case *types.Named: if _, isStruct := t.Underlying().(*types.Struct); !isStruct { @@ -211,10 +259,14 @@ func discoverFieldsRecursive(ctx context.Context, typ *types.Named, defaultValue defaultValue = appendAccessors(defaultValueAccessor, fieldPath, v.Name()) if isStringer(t) { defaultValue = defaultValue + ".String()" - } else { + } else if isJSONMarshaler(t) { logger.Infof(ctx, "Field [%v] of type [%v] does not implement Stringer interface."+ " Will use %s.mustMarshalJSON() to get its default value.", defaultValueAccessor, v.Name(), t.String()) defaultValue = fmt.Sprintf("%s.mustMarshalJSON(%s)", defaultValueAccessor, defaultValue) + } else { + logger.Infof(ctx, "Field [%v] of type [%v] does not implement Stringer interface."+ + " Will use %s.mustMarshalJSON() to get its default value.", defaultValueAccessor, v.Name(), t.String()) + defaultValue = fmt.Sprintf("%s.mustJsonMarshal(%s)", defaultValueAccessor, defaultValue) } } @@ -229,49 +281,66 @@ func discoverFieldsRecursive(ctx context.Context, typ *types.Named, defaultValue logger.Infof(logger.WithIndent(ctx, indent), "Type is json unmarhslalable.") fields = append(fields, FieldInfo{ - Name: tag.Name, - GoName: v.Name(), - Typ: types.Typ[types.String], - FlagMethodName: "String", - DefaultValue: defaultValue, - UsageString: tag.Usage, - TestValue: testValue, - TestStrategy: JSON, + Name: tag.Name, + GoName: v.Name(), + Typ: types.Typ[types.String], + FlagMethodName: "String", + DefaultValue: defaultValue, + UsageString: tag.Usage, + TestValue: testValue, + TestStrategy: JSON, + ShouldBindDefault: bindDefaultVar, }) } else { logger.Infof(ctx, "Traversing fields in type.") - nested, err := discoverFieldsRecursive(logger.WithIndent(ctx, indent), t, defaultValueAccessor, appendAccessors(fieldPath, v.Name())) + nested, err := discoverFieldsRecursive(logger.WithIndent(ctx, indent), t, defaultValueAccessor, appendAccessors(fieldPath, v.Name()), bindDefaultVar) if err != nil { return nil, err } for _, subField := range nested { fields = append(fields, FieldInfo{ - Name: fmt.Sprintf("%v.%v", tag.Name, subField.Name), - GoName: fmt.Sprintf("%v.%v", v.Name(), subField.GoName), - Typ: subField.Typ, - FlagMethodName: subField.FlagMethodName, - DefaultValue: subField.DefaultValue, - UsageString: subField.UsageString, - TestValue: subField.TestValue, - TestStrategy: subField.TestStrategy, + Name: fmt.Sprintf("%v.%v", tag.Name, subField.Name), + GoName: fmt.Sprintf("%v.%v", v.Name(), subField.GoName), + Typ: subField.Typ, + FlagMethodName: subField.FlagMethodName, + DefaultValue: subField.DefaultValue, + UsageString: subField.UsageString, + TestValue: subField.TestValue, + TestStrategy: subField.TestStrategy, + ShouldBindDefault: bindDefaultVar, }) } } case *types.Slice: logger.Infof(ctx, "[%v] is of a slice type with default value [%v].", tag.Name, tag.DefaultValue) + defaultValue := tag.DefaultValue - f, err := buildFieldForSlice(logger.WithIndent(ctx, indent), t, tag.Name, v.Name(), tag.Usage, tag.DefaultValue) + f, err := buildFieldForSlice(logger.WithIndent(ctx, indent), t, tag.Name, v.Name(), tag.Usage, defaultValue, bindDefaultVar) if err != nil { return nil, err } fields = append(fields, f) case *types.Array: - logger.Infof(ctx, "[%v] is of an array with default value [%v].", tag.Name, tag.DefaultValue) + logger.Infof(ctx, "[%v] is of an array type with default value [%v].", tag.Name, tag.DefaultValue) + defaultValue := tag.DefaultValue + + f, err := buildFieldForSlice(logger.WithIndent(ctx, indent), t, tag.Name, v.Name(), tag.Usage, defaultValue, bindDefaultVar) + if err != nil { + return nil, err + } + + fields = append(fields, f) + case *types.Map: + logger.Infof(ctx, "[%v] is of a map type with default value [%v].", tag.Name, tag.DefaultValue) + defaultValue := tag.DefaultValue + if len(defaultValueAccessor) > 0 { + defaultValue = appendAccessors(defaultValueAccessor, fieldPath, v.Name()) + } - f, err := buildFieldForSlice(logger.WithIndent(ctx, indent), t, tag.Name, v.Name(), tag.Usage, tag.DefaultValue) + f, err := buildFieldForMap(logger.WithIndent(ctx, indent), t, tag.Name, v.Name(), tag.Usage, defaultValue, bindDefaultVar) if err != nil { return nil, err } @@ -288,7 +357,7 @@ func discoverFieldsRecursive(ctx context.Context, typ *types.Named, defaultValue // NewGenerator initializes a PFlagProviderGenerator for pflags files for targetTypeName struct under pkg. If pkg is not filled in, // it's assumed to be current package (which is expected to be the common use case when invoking pflags from // go:generate comments) -func NewGenerator(pkg, targetTypeName, defaultVariableName string) (*PFlagProviderGenerator, error) { +func NewGenerator(pkg, targetTypeName, defaultVariableName string, shouldBindDefaultVar bool) (*PFlagProviderGenerator, error) { ctx := context.Background() var err error @@ -334,9 +403,10 @@ func NewGenerator(pkg, targetTypeName, defaultVariableName string) (*PFlagProvid } return &PFlagProviderGenerator{ - st: st, - pkg: targetPackage, - defaultVar: defaultVar, + st: st, + pkg: targetPackage, + defaultVar: defaultVar, + shouldBindDefaultVar: shouldBindDefaultVar, }, nil } @@ -369,7 +439,7 @@ func (g PFlagProviderGenerator) Generate(ctx context.Context) (PFlagProvider, er defaultValueAccessor = g.defaultVar.Name() } - fields, err := discoverFieldsRecursive(ctx, g.st, defaultValueAccessor, "") + fields, err := discoverFieldsRecursive(ctx, g.st, defaultValueAccessor, "", g.shouldBindDefaultVar) if err != nil { return PFlagProvider{}, err } diff --git a/cli/pflags/api/generator_test.go b/cli/pflags/api/generator_test.go index cbff9382..e8240c8 100644 --- a/cli/pflags/api/generator_test.go +++ b/cli/pflags/api/generator_test.go @@ -3,6 +3,9 @@ package api import ( "context" "flag" + "fmt" + "go/token" + "go/types" "io/ioutil" "os" "path/filepath" @@ -45,11 +48,10 @@ func TestElemValueOrNil(t *testing.T) { } func TestNewGenerator(t *testing.T) { - g, err := NewGenerator("github.com/flyteorg/flytestdlib/cli/pflags/api", "TestType", "DefaultTestType") + g, err := NewGenerator("github.com/flyteorg/flytestdlib/cli/pflags/api", "TestType", "DefaultTestType", false) if !assert.NoError(t, err) { t.FailNow() } - ctx := context.Background() p, err := g.Generate(ctx) if !assert.NoError(t, err) { @@ -93,4 +95,89 @@ func TestNewGenerator(t *testing.T) { goldenTestOutput, err := ioutil.ReadFile(filepath.Clean(goldenTestFilePath)) assert.NoError(t, err) assert.Equal(t, string(goldenTestOutput), string(testBytes)) + t.Run("empty package", func(t *testing.T) { + gen, err := NewGenerator("", "TestType", "DefaultTestType", false) + assert.Nil(t, err) + assert.NotNil(t, gen.GetTargetPackage()) + }) +} + +func TestBuildFieldForMap(t *testing.T) { + t.Run("supported : StringToString", func(t *testing.T) { + ctx := context.Background() + key := types.Typ[types.String] + elem := types.Typ[types.String] + typesMap := types.NewMap(key, elem) + name := "m" + goName := "StringMap" + usage := "I'm a map of strings" + defaultValue := "DefaultValue" + fieldInfo, err := buildFieldForMap(ctx, typesMap, name, goName, usage, defaultValue, false) + assert.Nil(t, err) + assert.NotNil(t, fieldInfo) + assert.Equal(t, "StringToString", fieldInfo.FlagMethodName) + assert.Equal(t, defaultValue, fieldInfo.DefaultValue) + }) + t.Run("unsupported : not a string type map", func(t *testing.T) { + ctx := context.Background() + key := types.Typ[types.Bool] + elem := types.Typ[types.Bool] + typesMap := types.NewMap(key, elem) + name := "m" + goName := "BoolMap" + usage := "I'm a map of bools" + defaultValue := "" + fieldInfo, err := buildFieldForMap(ctx, typesMap, name, goName, usage, defaultValue, false) + assert.Nil(t, err) + assert.NotNil(t, fieldInfo) + assert.Equal(t, "StringToString", fieldInfo.FlagMethodName) + assert.Equal(t, "nil", fieldInfo.DefaultValue) + }) + t.Run("unsupported : elem not a basic type", func(t *testing.T) { + ctx := context.Background() + key := types.Typ[types.String] + elem := &types.Interface{} + typesMap := types.NewMap(key, elem) + name := "m" + goName := "InterfaceMap" + usage := "I'm a map of interface values" + defaultValue := "" + fieldInfo, err := buildFieldForMap(ctx, typesMap, name, goName, usage, defaultValue, false) + assert.NotNil(t, err) + assert.Equal(t, fmt.Errorf("map of type [interface{/* incomplete */}] is not supported."+ + " Only basic slices or slices of json-unmarshalable types are supported"), err) + assert.NotNil(t, fieldInfo) + assert.Equal(t, "", fieldInfo.FlagMethodName) + assert.Equal(t, "", fieldInfo.DefaultValue) + }) + t.Run("supported : StringToFloat64", func(t *testing.T) { + ctx := context.Background() + key := types.Typ[types.String] + elem := types.Typ[types.Float64] + typesMap := types.NewMap(key, elem) + name := "m" + goName := "Float64Map" + usage := "I'm a map of float64" + defaultValue := "DefaultValue" + fieldInfo, err := buildFieldForMap(ctx, typesMap, name, goName, usage, defaultValue, false) + assert.Nil(t, err) + assert.NotNil(t, fieldInfo) + assert.Equal(t, "StringToFloat64", fieldInfo.FlagMethodName) + assert.Equal(t, defaultValue, fieldInfo.DefaultValue) + }) +} + +func TestDiscoverFieldsRecursive(t *testing.T) { + t.Run("empty struct", func(t *testing.T) { + ctx := context.Background() + defaultValueAccessor := "defaultAccessor" + fieldPath := "field.Path" + pkg := types.NewPackage("p", "p") + n1 := types.NewTypeName(token.NoPos, pkg, "T1", nil) + namedTypes := types.NewNamed(n1, new(types.Struct), nil) + //namedTypes := types.NewNamed(n1, nil, nil) + fields, err := discoverFieldsRecursive(ctx, namedTypes, defaultValueAccessor, fieldPath, false) + assert.Nil(t, err) + assert.Equal(t, len(fields), 0) + }) } diff --git a/cli/pflags/api/sample.go b/cli/pflags/api/sample.go index 6d8e2ab..51d681f 100644 --- a/cli/pflags/api/sample.go +++ b/cli/pflags/api/sample.go @@ -22,6 +22,7 @@ type TestType struct { IgnoredMap map[string]string `json:"ignored-map" pflag:"-,"` StorageConfig storage.Config `json:"storage"` IntValue *int `json:"i"` + StringMap map[string]string `json:"m" pflag:",I'm a map of strings"` } type NestedType struct { diff --git a/cli/pflags/api/templates.go b/cli/pflags/api/templates.go index 1505737..31799eb 100644 --- a/cli/pflags/api/templates.go +++ b/cli/pflags/api/templates.go @@ -44,6 +44,15 @@ func ({{ .Name }}) elemValueOrNil(v interface{}) interface{} { return v } +func ({{ .Name }}) mustJsonMarshal(v interface{}) string { + raw, err := json.Marshal(v) + if err != nil { + panic(err) + } + + return string(raw) +} + func ({{ .Name }}) mustMarshalJSON(v json.Marshaler) string { raw, err := v.MarshalJSON() if err != nil { @@ -58,8 +67,12 @@ func ({{ .Name }}) mustMarshalJSON(v json.Marshaler) string { func (cfg {{ .Name }}) GetPFlagSet(prefix string) *pflag.FlagSet { cmdFlags := pflag.NewFlagSet("{{ .Name }}", pflag.ExitOnError) {{- range .Fields }} + {{- if .ShouldBindDefault }} + cmdFlags.{{ .FlagMethodName }}Var(&{{ .DefaultValue }}, fmt.Sprintf("%v%v", prefix, "{{ .Name }}"), {{ .DefaultValue }}, {{ .UsageString }}) + {{- else }} cmdFlags.{{ .FlagMethodName }}(fmt.Sprintf("%v%v", prefix, "{{ .Name }}"), {{ .DefaultValue }}, {{ .UsageString }}) {{- end }} + {{- end }} return cmdFlags } `)) @@ -154,7 +167,7 @@ func testDecodeJson_{{ .Name }}(t *testing.T, val, result interface{}) { assert.NoError(t, decode_{{ .Name }}(val, result)) } -func testDecodeSlice_{{ .Name }}(t *testing.T, vStringSlice, result interface{}) { +func testDecodeRaw_{{ .Name }}(t *testing.T, vStringSlice, result interface{}) { assert.NoError(t, decode_{{ .Name }}(vStringSlice, result)) } @@ -172,6 +185,7 @@ func Test{{ .Name }}_SetFlags(t *testing.T) { {{ $ParentName := .Name }} {{- range .Fields }} t.Run("Test_{{ .Name }}", func(t *testing.T) { {{ $varName := print "v" .FlagMethodName }} + {{- if .ShouldTestDefault }} t.Run("DefaultValue", func(t *testing.T) { // Test that default value is set properly if {{ $varName }}, err := cmdFlags.Get{{ .FlagMethodName }}("{{ .Name }}"); err == nil { @@ -180,17 +194,18 @@ func Test{{ .Name }}_SetFlags(t *testing.T) { assert.FailNow(t, err.Error()) } }) + {{- end }} t.Run("Override", func(t *testing.T) { {{ if eq .TestStrategy "Json" }}testValue := {{ .TestValue }} - {{ else if eq .TestStrategy "SliceRaw" }}testValue := {{ .TestValue }} + {{ else if eq .TestStrategy "Raw" }}testValue := {{ .TestValue }} {{ else }}testValue := join_{{ $ParentName }}({{ .TestValue }}, ",") {{ end }} cmdFlags.Set("{{ .Name }}", testValue) if {{ $varName }}, err := cmdFlags.Get{{ .FlagMethodName }}("{{ .Name }}"); err == nil { {{ if eq .TestStrategy "Json" }}testDecodeJson_{{ $ParentName }}(t, fmt.Sprintf("%v", {{ print "v" .FlagMethodName }}), &actual.{{ .GoName }}) - {{ else if eq .TestStrategy "SliceRaw" }}testDecodeSlice_{{ $ParentName }}(t, {{ print "v" .FlagMethodName }}, &actual.{{ .GoName }}) - {{ else }}testDecodeSlice_{{ $ParentName }}(t, join_{{ $ParentName }}({{ print "v" .FlagMethodName }}, ","), &actual.{{ .GoName }}) + {{ else if eq .TestStrategy "Raw" }}testDecodeRaw_{{ $ParentName }}(t, {{ print "v" .FlagMethodName }}, &actual.{{ .GoName }}) + {{ else }}testDecodeRaw_{{ $ParentName }}(t, join_{{ $ParentName }}({{ print "v" .FlagMethodName }}, ","), &actual.{{ .GoName }}) {{ end }} } else { assert.FailNow(t, err.Error()) diff --git a/cli/pflags/api/testdata/testtype.go b/cli/pflags/api/testdata/testtype.go index 05feb6b..045a9c2 100755 --- a/cli/pflags/api/testdata/testtype.go +++ b/cli/pflags/api/testdata/testtype.go @@ -28,6 +28,15 @@ func (TestType) elemValueOrNil(v interface{}) interface{} { return v } +func (TestType) mustJsonMarshal(v interface{}) string { + raw, err := json.Marshal(v) + if err != nil { + panic(err) + } + + return string(raw) +} + func (TestType) mustMarshalJSON(v json.Marshaler) string { raw, err := v.MarshalJSON() if err != nil { @@ -47,7 +56,7 @@ func (cfg TestType) GetPFlagSet(prefix string) *pflag.FlagSet { cmdFlags.IntSlice(fmt.Sprintf("%v%v", prefix, "ints"), []int{12, 1}, "") cmdFlags.StringSlice(fmt.Sprintf("%v%v", prefix, "strs"), []string{"12", "1"}, "") cmdFlags.StringSlice(fmt.Sprintf("%v%v", prefix, "complexArr"), []string{}, "") - cmdFlags.String(fmt.Sprintf("%v%v", prefix, "c"), DefaultTestType.mustMarshalJSON(DefaultTestType.StringToJSON), "I'm a complex type but can be converted from string.") + cmdFlags.String(fmt.Sprintf("%v%v", prefix, "c"), DefaultTestType.mustJsonMarshal(DefaultTestType.StringToJSON), "I'm a complex type but can be converted from string.") cmdFlags.String(fmt.Sprintf("%v%v", prefix, "storage.type"), DefaultTestType.StorageConfig.Type, "Sets the type of storage to configure [s3/minio/local/mem/stow].") cmdFlags.String(fmt.Sprintf("%v%v", prefix, "storage.connection.endpoint"), DefaultTestType.StorageConfig.Connection.Endpoint.String(), "URL for storage client to connect to.") cmdFlags.String(fmt.Sprintf("%v%v", prefix, "storage.connection.auth-type"), DefaultTestType.StorageConfig.Connection.AuthType, "Auth Type to use [iam, accesskey].") @@ -62,5 +71,6 @@ func (cfg TestType) GetPFlagSet(prefix string) *pflag.FlagSet { cmdFlags.Int64(fmt.Sprintf("%v%v", prefix, "storage.limits.maxDownloadMBs"), DefaultTestType.StorageConfig.Limits.GetLimitMegabytes, "Maximum allowed download size (in MBs) per call.") cmdFlags.String(fmt.Sprintf("%v%v", prefix, "storage.defaultHttpClient.timeout"), DefaultTestType.StorageConfig.DefaultHTTPClient.Timeout.String(), "Sets time out on the http client.") cmdFlags.Int(fmt.Sprintf("%v%v", prefix, "i"), DefaultTestType.elemValueOrNil(DefaultTestType.IntValue).(int), "") + cmdFlags.StringToString(fmt.Sprintf("%v%v", prefix, "m"), DefaultTestType.StringMap, "I'm a map of strings") return cmdFlags } diff --git a/cli/pflags/api/testdata/testtype_test.go b/cli/pflags/api/testdata/testtype_test.go index 3854a31..cb35842 100755 --- a/cli/pflags/api/testdata/testtype_test.go +++ b/cli/pflags/api/testdata/testtype_test.go @@ -84,7 +84,7 @@ func testDecodeJson_TestType(t *testing.T, val, result interface{}) { assert.NoError(t, decode_TestType(val, result)) } -func testDecodeSlice_TestType(t *testing.T, vStringSlice, result interface{}) { +func testDecodeRaw_TestType(t *testing.T, vStringSlice, result interface{}) { assert.NoError(t, decode_TestType(vStringSlice, result)) } @@ -100,14 +100,6 @@ func TestTestType_SetFlags(t *testing.T) { assert.True(t, cmdFlags.HasFlags()) t.Run("Test_str", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("str"); err == nil { - assert.Equal(t, string(DefaultTestType.StringValue), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -122,14 +114,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_bl", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vBool, err := cmdFlags.GetBool("bl"); err == nil { - assert.Equal(t, bool(DefaultTestType.BoolValue), vBool) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -144,14 +128,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_nested.i", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vInt, err := cmdFlags.GetInt("nested.i"); err == nil { - assert.Equal(t, int(DefaultTestType.NestedType.IntValue), vInt) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -166,21 +142,13 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_ints", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vIntSlice, err := cmdFlags.GetIntSlice("ints"); err == nil { - assert.Equal(t, []int([]int{12, 1}), vIntSlice) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := join_TestType([]int{12, 1}, ",") cmdFlags.Set("ints", testValue) if vIntSlice, err := cmdFlags.GetIntSlice("ints"); err == nil { - testDecodeSlice_TestType(t, join_TestType(vIntSlice, ","), &actual.IntArray) + testDecodeRaw_TestType(t, join_TestType(vIntSlice, ","), &actual.IntArray) } else { assert.FailNow(t, err.Error()) @@ -188,21 +156,13 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_strs", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vStringSlice, err := cmdFlags.GetStringSlice("strs"); err == nil { - assert.Equal(t, []string([]string{"12", "1"}), vStringSlice) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := join_TestType([]string{"12", "1"}, ",") cmdFlags.Set("strs", testValue) if vStringSlice, err := cmdFlags.GetStringSlice("strs"); err == nil { - testDecodeSlice_TestType(t, join_TestType(vStringSlice, ","), &actual.StringArray) + testDecodeRaw_TestType(t, join_TestType(vStringSlice, ","), &actual.StringArray) } else { assert.FailNow(t, err.Error()) @@ -210,21 +170,13 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_complexArr", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vStringSlice, err := cmdFlags.GetStringSlice("complexArr"); err == nil { - assert.Equal(t, []string([]string{}), vStringSlice) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1,1" cmdFlags.Set("complexArr", testValue) if vStringSlice, err := cmdFlags.GetStringSlice("complexArr"); err == nil { - testDecodeSlice_TestType(t, vStringSlice, &actual.ComplexJSONArray) + testDecodeRaw_TestType(t, vStringSlice, &actual.ComplexJSONArray) } else { assert.FailNow(t, err.Error()) @@ -232,17 +184,9 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_c", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("c"); err == nil { - assert.Equal(t, string(DefaultTestType.mustMarshalJSON(DefaultTestType.StringToJSON)), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { - testValue := DefaultTestType.mustMarshalJSON(DefaultTestType.StringToJSON) + testValue := DefaultTestType.mustJsonMarshal(DefaultTestType.StringToJSON) cmdFlags.Set("c", testValue) if vString, err := cmdFlags.GetString("c"); err == nil { @@ -254,14 +198,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.type", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.type"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.Type), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -276,14 +212,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.connection.endpoint", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.connection.endpoint"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.Connection.Endpoint.String()), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := DefaultTestType.StorageConfig.Connection.Endpoint.String() @@ -298,14 +226,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.connection.auth-type", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.connection.auth-type"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.Connection.AuthType), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -320,14 +240,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.connection.access-key", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.connection.access-key"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.Connection.AccessKey), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -342,14 +254,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.connection.secret-key", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.connection.secret-key"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.Connection.SecretKey), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -364,14 +268,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.connection.region", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.connection.region"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.Connection.Region), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -386,14 +282,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.connection.disable-ssl", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vBool, err := cmdFlags.GetBool("storage.connection.disable-ssl"); err == nil { - assert.Equal(t, bool(DefaultTestType.StorageConfig.Connection.DisableSSL), vBool) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -408,14 +296,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.container", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.container"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.InitContainer), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -430,14 +310,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.enable-multicontainer", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vBool, err := cmdFlags.GetBool("storage.enable-multicontainer"); err == nil { - assert.Equal(t, bool(DefaultTestType.StorageConfig.MultiContainerEnabled), vBool) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -452,14 +324,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.cache.max_size_mbs", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vInt, err := cmdFlags.GetInt("storage.cache.max_size_mbs"); err == nil { - assert.Equal(t, int(DefaultTestType.StorageConfig.Cache.MaxSizeMegabytes), vInt) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -474,14 +338,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.cache.target_gc_percent", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vInt, err := cmdFlags.GetInt("storage.cache.target_gc_percent"); err == nil { - assert.Equal(t, int(DefaultTestType.StorageConfig.Cache.TargetGCPercent), vInt) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -496,14 +352,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.limits.maxDownloadMBs", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vInt64, err := cmdFlags.GetInt64("storage.limits.maxDownloadMBs"); err == nil { - assert.Equal(t, int64(DefaultTestType.StorageConfig.Limits.GetLimitMegabytes), vInt64) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := "1" @@ -518,14 +366,6 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_storage.defaultHttpClient.timeout", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly - if vString, err := cmdFlags.GetString("storage.defaultHttpClient.timeout"); err == nil { - assert.Equal(t, string(DefaultTestType.StorageConfig.DefaultHTTPClient.Timeout.String()), vString) - } else { - assert.FailNow(t, err.Error()) - } - }) t.Run("Override", func(t *testing.T) { testValue := DefaultTestType.StorageConfig.DefaultHTTPClient.Timeout.String() @@ -540,21 +380,27 @@ func TestTestType_SetFlags(t *testing.T) { }) }) t.Run("Test_i", func(t *testing.T) { - t.Run("DefaultValue", func(t *testing.T) { - // Test that default value is set properly + + t.Run("Override", func(t *testing.T) { + testValue := "1" + + cmdFlags.Set("i", testValue) if vInt, err := cmdFlags.GetInt("i"); err == nil { - assert.Equal(t, int(DefaultTestType.elemValueOrNil(DefaultTestType.IntValue).(int)), vInt) + testDecodeJson_TestType(t, fmt.Sprintf("%v", vInt), &actual.IntValue) + } else { assert.FailNow(t, err.Error()) } }) + }) + t.Run("Test_m", func(t *testing.T) { t.Run("Override", func(t *testing.T) { - testValue := "1" + testValue := "a=1,b=2" - cmdFlags.Set("i", testValue) - if vInt, err := cmdFlags.GetInt("i"); err == nil { - testDecodeJson_TestType(t, fmt.Sprintf("%v", vInt), &actual.IntValue) + cmdFlags.Set("m", testValue) + if vStringToString, err := cmdFlags.GetStringToString("m"); err == nil { + testDecodeRaw_TestType(t, vStringToString, &actual.StringMap) } else { assert.FailNow(t, err.Error()) diff --git a/cli/pflags/api/types.go b/cli/pflags/api/types.go index 1e6c129..c4932bd 100644 --- a/cli/pflags/api/types.go +++ b/cli/pflags/api/types.go @@ -11,18 +11,20 @@ type TestStrategy string const ( JSON TestStrategy = "Json" SliceJoined TestStrategy = "SliceJoined" - SliceRaw TestStrategy = "SliceRaw" + Raw TestStrategy = "Raw" ) type FieldInfo struct { - Name string - GoName string - Typ types.Type - DefaultValue string - UsageString string - FlagMethodName string - TestValue string - TestStrategy TestStrategy + Name string + GoName string + Typ types.Type + DefaultValue string + UsageString string + FlagMethodName string + TestValue string + TestStrategy TestStrategy + ShouldBindDefault bool + ShouldTestDefault bool } // Holds the finalized information passed to the template for evaluation. diff --git a/cli/pflags/api/utils.go b/cli/pflags/api/utils.go index b6a5b75..504aa0d 100644 --- a/cli/pflags/api/utils.go +++ b/cli/pflags/api/utils.go @@ -24,6 +24,10 @@ func isJSONUnmarshaler(t types.Type) bool { return implementsAnyOfMethods(t, "UnmarshalJSON") } +func isJSONMarshaler(t types.Type) bool { + return implementsAnyOfMethods(t, "MarshalJSON") +} + func isStringer(t types.Type) bool { return implementsAnyOfMethods(t, "String") } diff --git a/cli/pflags/cmd/root.go b/cli/pflags/cmd/root.go index d03c207..8ff3766 100644 --- a/cli/pflags/cmd/root.go +++ b/cli/pflags/cmd/root.go @@ -12,8 +12,9 @@ import ( ) var ( - pkg string - defaultValuesVariable string + pkg string + defaultValuesVariable string + shouldBindDefaultVariable bool ) var root = cobra.Command{ @@ -33,6 +34,7 @@ type MyStruct struct { func init() { root.Flags().StringVarP(&pkg, "package", "p", ".", "Determines the source/destination package.") root.Flags().StringVar(&defaultValuesVariable, "default-var", "defaultConfig", "Points to a variable to use to load default configs. If specified & found, it'll be used instead of the values specified in the tag.") + root.Flags().BoolVar(&shouldBindDefaultVariable, "bind-default-var", false, "The generated PFlags Set will bind fields to the default variable.") } func Execute() error { @@ -46,7 +48,7 @@ func generatePflagsProvider(cmd *cobra.Command, args []string) error { } ctx := context.Background() - gen, err := api.NewGenerator(pkg, structName, defaultValuesVariable) + gen, err := api.NewGenerator(pkg, structName, defaultValuesVariable, shouldBindDefaultVariable) if err != nil { return err } diff --git a/go.mod b/go.mod index 33c6dc2..a1f0ab9 100644 --- a/go.mod +++ b/go.mod @@ -54,5 +54,4 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect k8s.io/apimachinery v0.20.2 k8s.io/client-go v0.0.0-20210217172142-7279fc64d847 - k8s.io/klog/v2 v2.5.0 // indirect ) diff --git a/go.sum b/go.sum index 14d9131..15e8a5a 100644 --- a/go.sum +++ b/go.sum @@ -6,7 +6,6 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0 h1:GGslhk/BU052LPlnI1vpp3fcbUs+hQ3E+Doti/3/vF8= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= @@ -36,7 +35,6 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.12.0 h1:4y3gHptW1EHVtcPAVE0eBBlFuGqEejTTG3KdIE0lUX4= cloud.google.com/go/storage v1.12.0/go.mod h1:fFLk2dp2oAhDz8QFKwqrjdJvxSp/W2g7nillojlL5Ho= @@ -59,7 +57,9 @@ github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8K github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= @@ -71,6 +71,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= @@ -111,6 +112,7 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -140,6 +142,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= @@ -246,11 +249,14 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -272,6 +278,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -317,11 +324,13 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -330,7 +339,9 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -343,9 +354,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= @@ -485,10 +498,13 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -593,6 +609,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -835,6 +852,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -914,6 +932,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=