From c02bf19fc5b4810a4b0fb0340639e2bd78476706 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 21 Oct 2021 20:03:58 +0200 Subject: [PATCH] config: fix reflection parsing in LiT In the case where lnd's config struct is embedded inside another struct (for example in lightning-terminal), the flag won't be found under its original name. So we try to also look it up under the prefixed name. --- config.go | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/config.go b/config.go index f3dc063d6..158e152be 100644 --- a/config.go +++ b/config.go @@ -717,21 +717,43 @@ func ValidateConfig(cfg Config, usageMessage string, // IsSet returns true if an option has been set in either the config // file or by a flag. isSet := func(field string) bool { - fieldname, ok := reflect.TypeOf(Config{}).FieldByName(field) + fieldName, ok := reflect.TypeOf(Config{}).FieldByName(field) if !ok { - fmt.Fprintf(os.Stderr, "could not find field %s\n", field) + str := "%s: could not find field %s" + err := fmt.Errorf(str, funcName, field) + _, _ = fmt.Fprintln(os.Stderr, err) return false } - long, ok := fieldname.Tag.Lookup("long") + long, ok := fieldName.Tag.Lookup("long") if !ok { - fmt.Fprintf(os.Stderr, - "field %s does not have a long tag\n", field) + str := "%s: field %s does not have a long tag" + err := fmt.Errorf(str, funcName, field) + _, _ = fmt.Fprintln(os.Stderr, err) return false } - return fileParser.FindOptionByLongName(long).IsSet() || - flagParser.FindOptionByLongName(long).IsSet() + // The user has the option to set the flag in either the config + // file or as a command line flag. If any is set, we consider it + // to be set, not applying any precedence rules here (since it + // is a boolean the default is false anyway which would screw up + // any precedence rules). Additionally, we need to also support + // the use case where the config struct is embedded _within_ + // another struct with a prefix (as is the case with + // lightning-terminal). + fileOption := fileParser.FindOptionByLongName(long) + fileOptionNested := fileParser.FindOptionByLongName( + "lnd." + long, + ) + flagOption := flagParser.FindOptionByLongName(long) + flagOptionNested := flagParser.FindOptionByLongName( + "lnd." + long, + ) + + return (fileOption != nil && fileOption.IsSet()) || + (fileOptionNested != nil && fileOptionNested.IsSet()) || + (flagOption != nil && flagOption.IsSet()) || + (flagOptionNested != nil && flagOptionNested.IsSet()) } // As soon as we're done parsing configuration options, ensure all paths