From 68d793e57f9d3d72554e4ff4d7110673157e69a4 Mon Sep 17 00:00:00 2001 From: yangxikun Date: Sun, 25 Mar 2018 23:33:14 +0800 Subject: [PATCH 1/4] fix nested struct conflict & should not flatten nested field --- env_test.go | 3 +++ flag.go | 12 ++++++------ flag_test.go | 3 +++ multiconfig_test.go | 16 ++++++++++++++++ testdata/config.json | 8 +++++++- testdata/config.toml | 10 +++++++--- testdata/config.yaml | 5 +++++ 7 files changed, 47 insertions(+), 10 deletions(-) diff --git a/env_test.go b/env_test.go index af235a9..83174ad 100644 --- a/env_test.go +++ b/env_test.go @@ -90,11 +90,13 @@ func setEnvVars(t *testing.T, structName, prefix string) { "INTERVAL": "10s", "ID": "1234567890", "LABELS": "123,456", + "LOG_FILE": "/var/log/global.log", "POSTGRES_ENABLED": "true", "POSTGRES_PORT": "5432", "POSTGRES_HOSTS": "192.168.2.1,192.168.2.2,192.168.2.3", "POSTGRES_DBNAME": "configdb", "POSTGRES_AVAILABILITYRATIO": "8.23", + "POSTGRES_LOG_FILE": "/var/log/postgres.log", "POSTGRES_FOO": "8.23,9.12,11,90", } case "CamelCaseServer": @@ -112,6 +114,7 @@ func setEnvVars(t *testing.T, structName, prefix string) { "HOSTS": "192.168.2.1,192.168.2.2,192.168.2.3", "DBNAME": "configdb", "AVAILABILITYRATIO": "8.23", + "LOG_FILE": "/var/log/postgres.log", "FOO": "8.23,9.12,11,90", } } diff --git a/flag.go b/flag.go index 56cd64b..63cfba4 100644 --- a/flag.go +++ b/flag.go @@ -65,7 +65,7 @@ func (f *FlagLoader) Load(s interface{}) error { f.flagSet = flagSet for _, field := range strct.Fields() { - f.processField(field.Name(), field) + f.processField(field.Name(), field, 0) } flagSet.Usage = func() { @@ -92,7 +92,7 @@ func filterArgs(args []string) []string { r := []string{} for i := 0; i < len(args); i++ { if strings.Index(args[i], "test.") >= 0 { - if i + 1 < len(args) && strings.Index(args[i + 1], "-") == -1 { + if i+1 < len(args) && strings.Index(args[i+1], "-") == -1 { i++ } i++ @@ -106,7 +106,7 @@ func filterArgs(args []string) []string { // processField generates a flag based on the given field and fieldName. If a // nested struct is detected, a flag for each field of that nested struct is // generated too. -func (f *FlagLoader) processField(fieldName string, field *structs.Field) error { +func (f *FlagLoader) processField(fieldName string, field *structs.Field, nestedLevel int) error { if f.CamelCase { fieldName = strings.Join(camelcase.Split(fieldName), "-") fieldName = strings.Replace(fieldName, "---", "-", -1) @@ -115,9 +115,9 @@ func (f *FlagLoader) processField(fieldName string, field *structs.Field) error switch field.Kind() { case reflect.Struct: for _, ff := range field.Fields() { - flagName := field.Name() + "-" + ff.Name() + flagName := fieldName + "-" + ff.Name() - if f.Flatten { + if f.Flatten && nestedLevel == 0 { // first check if it's set or not, because if we have duplicate // we don't want to break the flag. Panic by giving a readable // output @@ -131,7 +131,7 @@ func (f *FlagLoader) processField(fieldName string, field *structs.Field) error flagName = ff.Name() } - if err := f.processField(flagName, ff); err != nil { + if err := f.processField(flagName, ff, nestedLevel+1); err != nil { return err } } diff --git a/flag_test.go b/flag_test.go index 9a88a91..f0e4751 100644 --- a/flag_test.go +++ b/flag_test.go @@ -201,11 +201,13 @@ func getFlags(t *testing.T, structName, prefix string) []string { "-interval": "10s", "-id": "1234567890", "-labels": "123,456", + "-log-file": "/var/log/global.log", "-postgres-enabled": "", "-postgres-port": "5432", "-postgres-hosts": "192.168.2.1,192.168.2.2,192.168.2.3", "-postgres-dbname": "configdb", "-postgres-availabilityratio": "8.23", + "-postgres-log-file": "/var/log/postgres.log", } case "FlattenedServer": flags = map[string]string{ @@ -214,6 +216,7 @@ func getFlags(t *testing.T, structName, prefix string) []string { "--hosts": "192.168.2.1,192.168.2.2,192.168.2.3", "--dbname": "configdb", "--availabilityratio": "8.23", + "-log-file": "/var/log/postgres.log", } case "FlattenedCamelCaseServer": flags = map[string]string{ diff --git a/multiconfig_test.go b/multiconfig_test.go index 3ff44ed..55f6f25 100644 --- a/multiconfig_test.go +++ b/multiconfig_test.go @@ -13,6 +13,7 @@ type ( Labels []int Enabled bool Users []string + Log Log Postgres Postgres unexported string Interval time.Duration @@ -25,6 +26,7 @@ type ( Hosts []string `required:"true"` DBName string `default:"configdb"` AvailabilityRatio float64 + Log Log unexported string } @@ -32,6 +34,10 @@ type ( Name string `required:"true"` Postgres `structs:",flatten"` } + + Log struct { + File string + } ) type FlattenedServer struct { @@ -60,12 +66,14 @@ func getDefaultServer() *Server { Labels: []int{123, 456}, Users: []string{"ankara", "istanbul"}, Interval: 10 * time.Second, + Log: Log{File: "/var/log/global.log"}, Postgres: Postgres{ Enabled: true, Port: 5432, Hosts: []string{"192.168.2.1", "192.168.2.2", "192.168.2.3"}, DBName: "configdb", AvailabilityRatio: 8.23, + Log: Log{File: "/var/log/postgres.log"}, }, } } @@ -154,6 +162,10 @@ func testStruct(t *testing.T, s *Server, d *Server) { } } + if s.Log.File != d.Log.File { + t.Errorf("Log value is wrong: %s, want: %s", s.Log.File, d.Log.File) + } + testPostgres(t, s.Postgres, d.Postgres) } @@ -180,6 +192,10 @@ func testPostgres(t *testing.T, s Postgres, d Postgres) { t.Errorf("AvailabilityRatio is wrong: %f, want: %f", s.AvailabilityRatio, d.AvailabilityRatio) } + if s.Log.File != d.Log.File { + t.Errorf("Postgres Log value is wrong: %s, want: %s", s.Log.File, d.Log.File) + } + if len(s.Hosts) != len(d.Hosts) { // do not continue testing if this fails, because others is depending on this test t.Fatalf("Hosts len is wrong: %v, want: %v", s.Hosts, d.Hosts) diff --git a/testdata/config.json b/testdata/config.json index 6c2e924..1d6ea32 100644 --- a/testdata/config.json +++ b/testdata/config.json @@ -11,6 +11,9 @@ "ankara", "istanbul" ], + "Log": { + "File": "/var/log/global.log" + }, "Postgres": { "Enabled": true, "Port": 5432, @@ -19,6 +22,9 @@ "192.168.2.2", "192.168.2.3" ], - "AvailabilityRatio": 8.23 + "AvailabilityRatio": 8.23, + "Log": { + "File": "/var/log/postgres.log" + } } } diff --git a/testdata/config.toml b/testdata/config.toml index bfc01a4..134e13f 100644 --- a/testdata/config.toml +++ b/testdata/config.toml @@ -1,12 +1,16 @@ Name = "koding" Enabled = true Users = ["ankara", "istanbul"] -Interval = 10000000000 -ID = 1234567890 -Labels = [123,456] +Interval = 10000000000 +ID = 1234567890 +Labels = [123,456] +[Log] +File = "/var/log/global.log" [Postgres] Enabled = true Port = 5432 Hosts = ["192.168.2.1", "192.168.2.2", "192.168.2.3"] AvailabilityRatio = 8.23 + [Postgres.Log] + File = "/var/log/postgres.log" diff --git a/testdata/config.yaml b/testdata/config.yaml index 8354703..e95b20d 100644 --- a/testdata/config.yaml +++ b/testdata/config.yaml @@ -16,6 +16,9 @@ labels: - 123 - 456 +log: + file: /var/log/global.log + # postgres configure postgres: enabled: true @@ -25,4 +28,6 @@ postgres: - 192.168.2.2 - 192.168.2.3 availabilityratio: 8.23 + log: + file: /var/log/postgres.log From 14b44d184946fc8246267b8be73ba49eeea7d2d3 Mon Sep 17 00:00:00 2001 From: yangxikun Date: Fri, 25 May 2018 12:15:40 +0800 Subject: [PATCH 2/4] add float32 type support --- multiconfig.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/multiconfig.go b/multiconfig.go index 0070344..26458c9 100644 --- a/multiconfig.go +++ b/multiconfig.go @@ -194,6 +194,15 @@ func fieldSet(field *structs.Field, v string) error { if err := field.Set(f); err != nil { return err } + case reflect.Float32: + f, err := strconv.ParseFloat(v, 32) + if err != nil { + return err + } + + if err := field.Set(float32(f)); err != nil { + return err + } case reflect.Int64: switch t := field.Value().(type) { case time.Duration: From 27d6dc4a44202b9b840e5f1126ffd041594ba5eb Mon Sep 17 00:00:00 2001 From: yangxikun Date: Fri, 22 Jun 2018 21:32:56 +0800 Subject: [PATCH 3/4] support raw command line args --- flag.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/flag.go b/flag.go index 63cfba4..549d005 100644 --- a/flag.go +++ b/flag.go @@ -9,6 +9,7 @@ import ( "github.com/fatih/camelcase" "github.com/fatih/structs" + "github.com/kballard/go-shellquote" ) // FlagLoader satisfies the loader interface. It creates on the fly flags based @@ -44,9 +45,12 @@ type FlagLoader struct { // By default it's flag.ContinueOnError. ErrorHandling flag.ErrorHandling - // Args defines a custom argument list. If nil, os.Args[1:] is used. + // Args defines a custom argument list. If nil and RawArgs is empty, os.Args[1:] is used. Args []string + // RawArgs define a custom shell command line args, When not empty and Args is nil. + RawArgs string + // FlagUsageFunc an optional function that is called to set a flag.Usage value // The input is the raw flag name, and the output should be a string // that will used in passed into the flag for Usage. @@ -83,6 +87,12 @@ func (f *FlagLoader) Load(s interface{}) error { args := filterArgs(os.Args[1:]) if f.Args != nil { args = f.Args + } else if f.RawArgs != "" { + var err error + args, err = shellquote.Split(f.RawArgs) + if err != nil { + return err + } } return flagSet.Parse(args) From 477e2879e6d64dc0464ef677df9a586c34404195 Mon Sep 17 00:00:00 2001 From: yangxikun Date: Tue, 28 Aug 2018 15:36:00 +0800 Subject: [PATCH 4/4] ADD: []float32 support --- multiconfig.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/multiconfig.go b/multiconfig.go index 26458c9..3f9bc13 100644 --- a/multiconfig.go +++ b/multiconfig.go @@ -178,6 +178,20 @@ func fieldSet(field *structs.Field, v string) error { list = append(list, i) } + if err := field.Set(list); err != nil { + return err + } + case []float32: + var list []float32 + for _, in := range strings.Split(v, ",") { + i, err := strconv.ParseFloat(in, 32) + if err != nil { + return err + } + + list = append(list, float32(i)) + } + if err := field.Set(list); err != nil { return err }