From 13bc378a6be16d32d6189cd7785a88ac1498b3a5 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 2 Feb 2023 17:06:03 +0100 Subject: [PATCH] Refactor the CreateFlags command * added the additional type flag, which can be bool,IP * UNDEF is recognized for the bool flag * 0.0.0.0 must be used as UNDEF for IP flag Signed-off-by: Christian Goll --- internal/app/wwctl/node/add/main.go | 5 + internal/app/wwctl/node/add/root.go | 4 +- internal/app/wwctl/node/set/main.go | 4 + internal/app/wwctl/node/set/root.go | 5 +- internal/app/wwctl/profile/add/main.go | 4 + internal/app/wwctl/profile/add/root.go | 3 +- internal/app/wwctl/profile/set/root.go | 5 +- internal/pkg/node/datastructure.go | 22 +-- internal/pkg/node/flags.go | 200 +++++++++++++++++++++++++ internal/pkg/node/methods.go | 8 +- internal/pkg/node/transformers.go | 97 ------------ 11 files changed, 241 insertions(+), 116 deletions(-) create mode 100644 internal/pkg/node/flags.go diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index d0d919a8..a3dec5aa 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" ) +<<<<<<< HEAD /* RunE needs a function of type func(*cobraCommand,[]string) err, but in order to avoid global variables which mess up testing a function of @@ -16,6 +17,10 @@ the required type is returned */ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { + // run converters for different types + for _, c := range Converters { + c() + } // remove the default network as all network values are assigned // to this network if _, ok := vars.nodeConf.NetDevs["default"]; ok && vars.netName != "" { diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go index c498187f..f36241ac 100644 --- a/internal/app/wwctl/node/add/root.go +++ b/internal/app/wwctl/node/add/root.go @@ -14,6 +14,7 @@ import ( type variables struct { netName string nodeConf node.NodeConf + converters []func() } // Returns the newly created command @@ -28,9 +29,8 @@ func GetCommand() *cobra.Command { RunE: CobraRunE(&vars), Args: cobra.MinimumNArgs(1), } - vars.nodeConf.CreateFlags(baseCmd, []string{"tagdel", "nettagdel", "ipmitagdel"}) + vars.converters = vars.nodeConf.CreateFlags(baseCmd, []string{"tagdel", "nettagdel", "ipmitagdel"}) baseCmd.PersistentFlags().StringVar(&vars.netName, "netname", "", "Set network name for network options") - // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 63dad15f..e95e77a2 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -13,6 +13,10 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { + // run converters for different types + for _, c := range Converters { + c() + } // remove the default network as the all network values are assigned // to this network if NetName != "default" { diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 0e5e81cf..e9cc48e9 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -15,7 +15,7 @@ var ( DisableFlagsInUseLine: true, Use: "set [OPTIONS] PATTERN [PATTERN ...]", Short: "Configure node properties", - Long: "This command sets configuration properties for nodes matching PATTERN.\n\nNote: use the string 'UNSET' to remove a configuration", + Long: "This command sets configuration properties for nodes matching PATTERN.\n\nNote: use the string 'UNSET'/'0.0.0.0' to remove a configuration", Args: cobra.MinimumNArgs(0), RunE: CobraRunE, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -38,11 +38,12 @@ var ( SetYes bool SetForce bool NodeConf node.NodeConf + Converters []func() ) func init() { NodeConf = node.NewConf() - NodeConf.CreateFlags(baseCmd, []string{}) + Converters = NodeConf.CreateFlags(baseCmd, []string{}) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().StringVar(&NetName, "netname", "default", "Set network name for network options") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go index 0260f232..e509e9d9 100644 --- a/internal/app/wwctl/profile/add/main.go +++ b/internal/app/wwctl/profile/add/main.go @@ -14,6 +14,10 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { + // run converters for different types + for _, c := range Converters { + c() + } // remove the default network as the all network values are assigned // to this network if NetName != "" { diff --git a/internal/app/wwctl/profile/add/root.go b/internal/app/wwctl/profile/add/root.go index e3ad6d24..2cfec736 100644 --- a/internal/app/wwctl/profile/add/root.go +++ b/internal/app/wwctl/profile/add/root.go @@ -25,12 +25,13 @@ var ( SetForce bool NetName string ProfileConf node.NodeConf + Converters []func() ) // GetRootCommand returns the root cobra.Command for the application. func GetCommand() *cobra.Command { ProfileConf = node.NewConf() - ProfileConf.CreateFlags(baseCmd, + Converters = ProfileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") // register the command line completions diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index f95cbb6c..c9af0599 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -15,7 +15,7 @@ var ( Use: "set [OPTIONS] [PROFILE ...]", Short: "Configure node profile properties", Long: "This command sets configuration properties for the node PROFILE(s).\n\n" + - "Note: use the string 'UNSET' to remove a configuration", + "Note: use the string 'UNSET'/'0.0.0.0' to remove a configuration", Args: cobra.MinimumNArgs(0), RunE: CobraRunE, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -38,11 +38,12 @@ var ( SetForce bool NetName string ProfileConf node.NodeConf + Converters []func() ) func init() { ProfileConf = node.NewConf() - ProfileConf.CreateFlags(baseCmd, + Converters = ProfileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) baseCmd.PersistentFlags().StringVar(&NetName, "netname", "default", "Set network name for network options") baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index cecd1db5..a4dab9c2 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -44,7 +44,7 @@ type NodeConf struct { Init string `yaml:"init,omitempty" lopt:"init" sopt:"i" comment:"Define the init process to boot the container"` Root string `yaml:"root,omitempty" lopt:"root" comment:"Define the rootfs" ` AssetKey string `yaml:"asset key,omitempty" lopt:"asset" comment:"Set the node's Asset tag (key)"` - Discoverable string `yaml:"discoverable,omitempty" lopt:"discoverable" comment:"Make discoverable in given network (yes/no)"` + Discoverable string `yaml:"discoverable,omitempty" lopt:"discoverable" sopt:"e" comment:"Make discoverable in given network (true/false)" type:"bool"` Profiles []string `yaml:"profiles,omitempty" lopt:"profile" sopt:"P" comment:"Set the node's profile members (comma separated)"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` Tags map[string]string `yaml:"tags,omitempty" lopt:"tagadd" comment:"base key"` @@ -56,12 +56,12 @@ type NodeConf struct { type IpmiConf struct { UserName string `yaml:"username,omitempty" lopt:"ipmiuser" comment:"Set the IPMI username"` Password string `yaml:"password,omitempty" lopt:"ipmipass" comment:"Set the IPMI password"` - Ipaddr string `yaml:"ipaddr,omitempty" lopt:"ipmiaddr" comment:"Set the IPMI IP address"` - Netmask string `yaml:"netmask,omitempty" lopt:"ipminetmask" comment:"Set the IPMI netmask"` + Ipaddr string `yaml:"ipaddr,omitempty" lopt:"ipmiaddr" comment:"Set the IPMI IP address" type:"IP"` + Netmask string `yaml:"netmask,omitempty" lopt:"ipminetmask" comment:"Set the IPMI netmask" type:"IP"` Port string `yaml:"port,omitempty" lopt:"ipmiport" comment:"Set the IPMI port"` - Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` + Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway" type:"IP"` Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` - Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` + Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (true/false)" type:"bool"` Tags map[string]string `yaml:"tags,omitempty" lopt:"ipmitagadd" comment:"add ipmitags"` TagsDel []string `yaml:"tagsdel,omitempty" lopt:"ipmitagdel" comment:"remove ipmitags"` // should not go to disk only to wire } @@ -73,16 +73,18 @@ type KernelConf struct { type NetDevs struct { Type string `yaml:"type,omitempty" lopt:"type" sopt:"T" comment:"Set device type of given network"` - OnBoot string `yaml:"onboot,omitempty" lopt:"onboot" comment:"Enable/disable network device (yes/no)"` + OnBoot string `yaml:"onboot,omitempty" lopt:"onboot" comment:"Enable/disable network device (true/false)" type:"bool"` Device string `yaml:"device,omitempty" lopt:"netdev" sopt:"N" comment:"Set the device for given network"` Hwaddr string `yaml:"hwaddr,omitempty" lopt:"hwaddr" sopt:"H" comment:"Set the device's HW address for given network"` - Ipaddr string `yaml:"ipaddr,omitempty" comment:"IPv4 address in given network" sopt:"I" lopt:"ipaddr"` + Ipaddr string `yaml:"ipaddr,omitempty" comment:"IPv4 address in given network" sopt:"I" lopt:"ipaddr" type:"IP"` IpCIDR string `yaml:"ipcidr,omitempty"` - Ipaddr6 string `yaml:"ip6addr,omitempty" lopt:"ipaddr6" comment:"IPv6 address"` + Ipaddr6 string `yaml:"ip6addr,omitempty" lopt:"ipaddr6" comment:"IPv6 address" type:"IP"` Prefix string `yaml:"prefix,omitempty"` - Netmask string `yaml:"netmask,omitempty" lopt:"netmask" sopt:"M" comment:"Set the networks netmask"` - Gateway string `yaml:"gateway,omitempty" lopt:"gateway" sopt:"G" comment:"Set the node's network device gateway"` + Netmask string `yaml:"netmask,omitempty" lopt:"netmask" sopt:"M" comment:"Set the networks netmask" type:"IP"` + Gateway string `yaml:"gateway,omitempty" lopt:"gateway" sopt:"G" comment:"Set the node's network device gateway" type:"IP"` MTU string `yaml:"mtu,omitempty" lopt:"mtu" comment:"Set the mtu"` + Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (true/false)" type:"bool"` + Default string `yaml:"default,omitempty"` /* backward compatibility */ Tags map[string]string `yaml:"tags,omitempty" lopt:"nettagadd" comment:"network tags"` TagsDel []string `yaml:"tagsdel,omitempty" lopt:"nettagdel" comment:"delete network tags"` // should not go to disk only to wire } diff --git a/internal/pkg/node/flags.go b/internal/pkg/node/flags.go new file mode 100644 index 00000000..8f42f91d --- /dev/null +++ b/internal/pkg/node/flags.go @@ -0,0 +1,200 @@ +package node + +import ( + "net" + "os" + "reflect" + "strconv" + "strings" + + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/spf13/cobra" +) + +/* +Create cmd line flags from the NodeConf fields +*/ +func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) (converters []func()) { + nodeInfoType := reflect.TypeOf(nodeConf) + nodeInfoVal := reflect.ValueOf(nodeConf) + // now iterate of every field + for i := 0; i < nodeInfoVal.Elem().NumField(); i++ { + if nodeInfoType.Elem().Field(i).Tag.Get("comment") != "" && + !util.InSlice(excludeList, nodeInfoType.Elem().Field(i).Tag.Get("lopt")) { + field := nodeInfoVal.Elem().Field(i) + converters = append(converters, createFlags(baseCmd, excludeList, nodeInfoType.Elem().Field(i), &field)...) + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { + nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + nestVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + for j := 0; j < nestType.Elem().NumField(); j++ { + field := nestVal.Elem().Field(j) + converters = append(converters, createFlags(baseCmd, excludeList, nestType.Elem().Field(j), &field)...) + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) { + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs) + // add a default network so that it can hold values + key := "default" + if len(netMap) == 0 { + netMap[key] = new(NetDevs) + } else { + for keyIt := range netMap { + key = keyIt + break + } + } + netType := reflect.TypeOf(netMap[key]) + netVal := reflect.ValueOf(netMap[key]) + for j := 0; j < netType.Elem().NumField(); j++ { + field := netVal.Elem().Field(j) + converters = append(converters, createFlags(baseCmd, excludeList, netType.Elem().Field(j), &field)...) + } + } + } + return converters +} + +/* +Helper function to create the different PerisitantFlags() for different types. +*/ +func createFlags(baseCmd *cobra.Command, excludeList []string, + myType reflect.StructField, myVal *reflect.Value) (converters []func()) { + if myType.Tag.Get("lopt") != "" { + if myType.Type.Kind() == reflect.String { + ptr := myVal.Addr().Interface().(*string) + switch myType.Tag.Get("type") { + case "uint": + defaultConv, _ := strconv.ParseUint(myType.Tag.Get("default"), 10, 32) + var valueRaw uint + converters = append(converters, func() { *ptr = strconv.FormatUint(uint64(valueRaw), 10) }) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().UintVarP(&valueRaw, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + uint(defaultConv), + myType.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().UintVar(&valueRaw, + myType.Tag.Get("lopt"), + uint(defaultConv), + myType.Tag.Get("comment")) + } + case "bool": + /* + Can't use the bool var from pflag as we need the UNSET verbs to be passwd correctly + */ + converters = append(converters, func() { + if !util.InSlice(GetUnsetVerbs(), *ptr) && *ptr != "" { + if strings.ToLower(*ptr) != "yes" { + *ptr = "true" + return + } + if strings.ToLower(*ptr) != "no" { + *ptr = "false" + return + } + val, err := strconv.ParseBool(*ptr) + if err != nil { + wwlog.Error("commandline option %s needs to be bool", myType.Tag.Get("lopt")) + os.Exit(1) + } + *ptr = strconv.FormatBool(val) + } + }) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringVarP(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + "", + myType.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().StringVar(ptr, + myType.Tag.Get("lopt"), + "", + myType.Tag.Get("comment")) + } + baseCmd.PersistentFlags().Lookup(myType.Tag.Get("lopt")).NoOptDefVal = "true" + case "IP": + defaultConv := net.ParseIP(myType.Tag.Get("default")) + var valueRaw net.IP + converters = append(converters, func() { + if valueRaw != nil { + *ptr = valueRaw.String() + } + }) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().IPVarP(&valueRaw, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + defaultConv, + myType.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().IPVar(&valueRaw, + myType.Tag.Get("lopt"), + defaultConv, + myType.Tag.Get("comment")) + } + case "IPMask": + defaultConv := net.ParseIP(myType.Tag.Get("default")).DefaultMask() + var valueRaw net.IPMask + converters = append(converters, func() { *ptr = valueRaw.String() }) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().IPMaskVarP(&valueRaw, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + defaultConv, + myType.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().IPMaskVar(&valueRaw, + myType.Tag.Get("lopt"), + defaultConv, + myType.Tag.Get("comment")) + } + default: + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringVarP(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + myType.Tag.Get("default"), + myType.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().StringVar(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("default"), + myType.Tag.Get("comment")) + } + } + } else if myType.Type == reflect.TypeOf([]string{}) { + ptr := myVal.Addr().Interface().(*[]string) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringSliceVarP(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + []string{myType.Tag.Get("default")}, + myType.Tag.Get("comment")) + } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { + baseCmd.PersistentFlags().StringSliceVar(ptr, + myType.Tag.Get("lopt"), + []string{myType.Tag.Get("default")}, + myType.Tag.Get("comment")) + + } + } else if myType.Type == reflect.TypeOf(map[string]string{}) { + ptr := myVal.Addr().Interface().(*map[string]string) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringToStringVarP(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + map[string]string{}, // empty default! + myType.Tag.Get("comment")) + } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { + baseCmd.PersistentFlags().StringToStringVar(ptr, + myType.Tag.Get("lopt"), + map[string]string{}, // empty default! + myType.Tag.Get("comment")) + + } + } + } + return converters +} diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 9f89255a..f9deb492 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -10,6 +10,10 @@ import ( "github.com/hpcng/warewulf/internal/pkg/wwlog" ) +func GetUnsetVerbs() []string { + return []string{"UNSET", "DELETE", "UNDEF", "undef", "--", "nil", "0.0.0.0"} +} + /********** * * Filters @@ -77,7 +81,7 @@ func (ent *Entry) Set(val string) { return } - if val == "UNDEF" || val == "DELETE" || val == "UNSET" || val == "--" || val == "nil" { + if util.InSlice(GetUnsetVerbs(), val) { wwlog.Debug("Removing value for %v", *ent) ent.value = []string{""} } else { @@ -102,7 +106,7 @@ func (ent *Entry) SetSlice(val []string) { } else if len(val) == 1 && val[0] == "" { // check also for an "empty" slice return } - if val[0] == "UNDEF" || val[0] == "DELETE" || val[0] == "UNSET" || val[0] == "--" { + if util.InSlice(GetUnsetVerbs(), val[0]) { ent.value = []string{} } else { ent.value = val diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 75960b25..4acaa859 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -6,7 +6,6 @@ import ( "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/spf13/cobra" ) /* @@ -194,102 +193,6 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, } } -/* -Create cmd line flags from the NodeConf fields -*/ -func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) { - nodeInfoType := reflect.TypeOf(nodeConf) - nodeInfoVal := reflect.ValueOf(nodeConf) - // now iterate of every field - for i := 0; i < nodeInfoVal.Elem().NumField(); i++ { - if nodeInfoType.Elem().Field(i).Tag.Get("comment") != "" && - !util.InSlice(excludeList, nodeInfoType.Elem().Field(i).Tag.Get("lopt")) { - field := nodeInfoVal.Elem().Field(i) - createFlags(baseCmd, excludeList, nodeInfoType.Elem().Field(i), &field) - } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { - nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) - nestVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) - for j := 0; j < nestType.Elem().NumField(); j++ { - field := nestVal.Elem().Field(j) - createFlags(baseCmd, excludeList, nestType.Elem().Field(j), &field) - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) { - netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs) - // add a default network so that it can hold values - key := "default" - if len(netMap) == 0 { - netMap[key] = new(NetDevs) - } else { - for keyIt := range netMap { - key = keyIt - break - } - } - netType := reflect.TypeOf(netMap[key]) - netVal := reflect.ValueOf(netMap[key]) - for j := 0; j < netType.Elem().NumField(); j++ { - field := netVal.Elem().Field(j) - createFlags(baseCmd, excludeList, netType.Elem().Field(j), &field) - } - } - } -} - -/* -Helper function to create the different PerisitantFlags() for different types. -*/ -func createFlags(baseCmd *cobra.Command, excludeList []string, - myType reflect.StructField, myVal *reflect.Value) { - if myType.Tag.Get("lopt") != "" { - if myType.Type.Kind() == reflect.String { - ptr := myVal.Addr().Interface().(*string) - if myType.Tag.Get("sopt") != "" { - baseCmd.PersistentFlags().StringVarP(ptr, - myType.Tag.Get("lopt"), - myType.Tag.Get("sopt"), - myType.Tag.Get("default"), - myType.Tag.Get("comment")) - } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { - baseCmd.PersistentFlags().StringVar(ptr, - myType.Tag.Get("lopt"), - myType.Tag.Get("default"), - myType.Tag.Get("comment")) - - } - } else if myType.Type == reflect.TypeOf([]string{}) { - ptr := myVal.Addr().Interface().(*[]string) - if myType.Tag.Get("sopt") != "" { - baseCmd.PersistentFlags().StringSliceVarP(ptr, - myType.Tag.Get("lopt"), - myType.Tag.Get("sopt"), - []string{myType.Tag.Get("default")}, - myType.Tag.Get("comment")) - } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { - baseCmd.PersistentFlags().StringSliceVar(ptr, - myType.Tag.Get("lopt"), - []string{myType.Tag.Get("default")}, - myType.Tag.Get("comment")) - - } - } else if myType.Type == reflect.TypeOf(map[string]string{}) { - ptr := myVal.Addr().Interface().(*map[string]string) - if myType.Tag.Get("sopt") != "" { - baseCmd.PersistentFlags().StringToStringVarP(ptr, - myType.Tag.Get("lopt"), - myType.Tag.Get("sopt"), - map[string]string{}, // empty default! - myType.Tag.Get("comment")) - } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { - baseCmd.PersistentFlags().StringToStringVar(ptr, - myType.Tag.Get("lopt"), - map[string]string{}, // empty default! - myType.Tag.Get("comment")) - - } - } - } -} - /* Populates all fields of NodeInfo with Set from the values of NodeConf.