added more abstrac setter for nested structs
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
package set
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/hpcng/warewulf/internal/pkg/container"
|
||||
"github.com/hpcng/warewulf/internal/pkg/kernel"
|
||||
@@ -33,10 +33,7 @@ var (
|
||||
return node_names, cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
}
|
||||
SetComment string
|
||||
SetContainer string
|
||||
SetKernelOverride string
|
||||
SetKernelArgs string
|
||||
SetNetName string
|
||||
SetNetDev string
|
||||
SetIpaddr string
|
||||
@@ -66,48 +63,27 @@ var (
|
||||
SetAddProfile []string
|
||||
SetDelProfile []string
|
||||
SetForce bool
|
||||
SetInit string
|
||||
SetDiscoverable bool
|
||||
SetUndiscoverable bool
|
||||
SetRoot string
|
||||
SetTags []string
|
||||
SetDelTags []string
|
||||
SetAssetKey string
|
||||
SetNetTags []string
|
||||
SetNetDelTags []string
|
||||
OptionStrMap map[string]*string
|
||||
KernelStrMapmap map[string]*string
|
||||
)
|
||||
|
||||
func init() {
|
||||
OptionStrMap = make(map[string]*string)
|
||||
//var emptyNodeConf node.NodeConf
|
||||
//var emptyKernelE node.KernelEntry
|
||||
myBase := node.CobraCommand{baseCmd}
|
||||
var emptyNodeConf node.NodeConf
|
||||
nodeStruct := reflect.ValueOf(emptyNodeConf)
|
||||
nodeType := nodeStruct.Type()
|
||||
for i := 0; i < nodeStruct.NumField(); i++ {
|
||||
field := nodeType.Field(i)
|
||||
if field.Tag.Get("comment") != "" {
|
||||
kind := field.Type.Kind()
|
||||
if kind == reflect.String {
|
||||
var optionVal string
|
||||
OptionStrMap[field.Name] = &optionVal
|
||||
if field.Tag.Get("sopt") != "" {
|
||||
baseCmd.PersistentFlags().StringVarP(&optionVal,
|
||||
field.Tag.Get("lopt"),
|
||||
field.Tag.Get("sopt"),
|
||||
field.Tag.Get("default"),
|
||||
field.Tag.Get("comment"))
|
||||
} else {
|
||||
baseCmd.PersistentFlags().StringVar(&optionVal,
|
||||
field.Tag.Get("lopt"),
|
||||
field.Tag.Get("default"),
|
||||
field.Tag.Get("comment"))
|
||||
emptyNodeConf.Kernel = new(node.KernelConf)
|
||||
emptyNodeConf.Ipmi = new(node.IpmiConf)
|
||||
//emptyNodeConf.NetDevs = make(map[string]*node.NetDevs)
|
||||
OptionStrMap = myBase.CreateFlags(emptyNodeConf)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//baseCmd.PersistentFlags().StringVar(&SetComment, "comment", "", "Set a comment for this node")
|
||||
baseCmd.PersistentFlags().StringVarP(&SetContainer, "container", "C", "", "Set the container (VNFS) for this node")
|
||||
fmt.Printf("OptionStrMap: %v\n", OptionStrMap)
|
||||
if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
list, _ := container.ListSources()
|
||||
return list, cobra.ShellCompDirectiveNoFileComp
|
||||
@@ -121,12 +97,8 @@ func init() {
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes")
|
||||
baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group")
|
||||
baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name")
|
||||
baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container")
|
||||
baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs")
|
||||
baseCmd.PersistentFlags().StringVar(&SetAssetKey, "assetkey", "", "Set the node's Asset tag (key)")
|
||||
baseCmd.PersistentFlags().StringVarP(&SetInitOverlay, "wwinit", "O", "", "Set the node's initialization overlay")
|
||||
baseCmd.PersistentFlags().StringSliceVarP(&SetRuntimeOverlay, "runtime", "R", []string{}, "Set the node's runtime overlay")
|
||||
if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
|
||||
@@ -19,9 +19,9 @@ type NodeYaml struct {
|
||||
NodeConf is the datastructure which is stored on disk.
|
||||
*/
|
||||
type NodeConf struct {
|
||||
Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set Comment"`
|
||||
Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set arbitrary string comment"`
|
||||
ClusterName string `yaml:"cluster name,omitempty"`
|
||||
ContainerName string `yaml:"container name,omitempty"`
|
||||
ContainerName string `yaml:"container name,omitempty" lopt:"container" sopt:"C" comment:"Set container name"`
|
||||
Ipxe string `yaml:"ipxe template,omitempty"`
|
||||
KernelVersion string `yaml:"kernel version,omitempty"`
|
||||
KernelOverride string `yaml:"kernel override,omitempty"`
|
||||
@@ -38,9 +38,9 @@ type NodeConf struct {
|
||||
SystemOverlay []string `yaml:"system overlay,omitempty"`
|
||||
Kernel *KernelConf `yaml:"kernel,omitempty"`
|
||||
Ipmi *IpmiConf `yaml:"ipmi,omitempty"`
|
||||
Init string `yaml:"init,omitempty"`
|
||||
Root string `yaml:"root,omitempty"`
|
||||
AssetKey string `yaml:"asset key,omitempty"`
|
||||
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"`
|
||||
Profiles []string `yaml:"profiles,omitempty"`
|
||||
NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"`
|
||||
@@ -61,7 +61,7 @@ type IpmiConf struct {
|
||||
type KernelConf struct {
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Override string `yaml:"override,omitempty"`
|
||||
Args string `yaml:"args,omitempty"`
|
||||
Args string `yaml:"args,omitempty" lopt:"kernelargs" sopt:"A" comment:"Set Kernel argument"`
|
||||
}
|
||||
|
||||
type NetDevs struct {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
/**********
|
||||
@@ -304,25 +305,152 @@ func (ent *Entry) Defined() bool {
|
||||
/*
|
||||
Set the Entry trough an interface by trying to cast the interface
|
||||
*/
|
||||
func SetEntry(entryPrt interface{}, val string) {
|
||||
fmt.Printf("entryPtr: %v\n", reflect.TypeOf(entryPrt))
|
||||
if entry, ok := entryPrt.(*Entry); ok {
|
||||
entry.Set(val)
|
||||
func SetEntry(entryPtr interface{}, val interface{}) {
|
||||
if reflect.TypeOf(entryPtr) == reflect.TypeOf((*Entry)(nil)) {
|
||||
entry := entryPtr.(*Entry)
|
||||
valKind := reflect.TypeOf(val)
|
||||
if valKind.Kind() == reflect.String {
|
||||
entry.Set(val.(string))
|
||||
} else if valKind.Kind() == reflect.Slice {
|
||||
if valKind.Elem().Kind() == reflect.String {
|
||||
entry.SetSlice(val.([]string))
|
||||
} else {
|
||||
panic("Got unknown slice type")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf("Can't convert %s to *node.Entry\n", reflect.TypeOf(entryPrt)))
|
||||
panic(fmt.Sprintf("Can't convert %s to *node.Entry\n", reflect.TypeOf(entryPtr)))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Call SetEntry for given field
|
||||
Call SetEntry for given field (NodeInfo)
|
||||
*/
|
||||
func (node *NodeInfo) SetField(fieldName string, val interface{}) {
|
||||
field := reflect.ValueOf(node).Elem().FieldByName(fieldName)
|
||||
if field.IsValid() {
|
||||
SetEntry(field.Addr().Interface(), val.(string))
|
||||
//fmt.Println(reflect.TypeOf(field.Addr().Interface()))
|
||||
SetEntry(field.Addr().Interface(), val)
|
||||
} else {
|
||||
panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName))
|
||||
fieldNames := strings.Split(fieldName, ".")
|
||||
if len(fieldNames) == 2 {
|
||||
nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0])
|
||||
if nestedField.IsValid() {
|
||||
switch nestedField.Addr().Type() {
|
||||
case reflect.TypeOf((**KernelEntry)(nil)):
|
||||
entry := nestedField.Addr().Interface().(**KernelEntry)
|
||||
(*entry).SetField(fieldNames[1], val)
|
||||
case reflect.TypeOf((**IpmiEntry)(nil)):
|
||||
entry := nestedField.Addr().Interface().(**IpmiEntry)
|
||||
(*entry).SetField(fieldNames[1], val)
|
||||
default:
|
||||
panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type()))
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName))
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Call SetEntry for given field (KernelEntry)
|
||||
*/
|
||||
func (node *KernelEntry) SetField(fieldName string, val interface{}) {
|
||||
field := reflect.ValueOf(node).Elem().FieldByName(fieldName)
|
||||
if field.IsValid() {
|
||||
SetEntry(field.Addr().Interface(), val)
|
||||
} else {
|
||||
panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Call SetEntry for given field (ImpiEntry)
|
||||
*/
|
||||
func (node *IpmiEntry) SetField(fieldName string, val interface{}) {
|
||||
field := reflect.ValueOf(node).Elem().FieldByName(fieldName)
|
||||
if field.IsValid() {
|
||||
SetEntry(field.Addr().Interface(), val)
|
||||
} else {
|
||||
panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get all names of the fields in the given struct (recursive)
|
||||
and create a map[name of struct field]*string if the the field
|
||||
of the struct bears the comment tag.
|
||||
*/
|
||||
func GetOptionsMap(theStruct interface{}) map[string]*string {
|
||||
optionsMap := make(map[string]*string)
|
||||
structVal := reflect.ValueOf(theStruct)
|
||||
structTyp := structVal.Type()
|
||||
for i := 0; i < structVal.NumField(); i++ {
|
||||
field := structTyp.Field(i)
|
||||
if field.Type.Kind() == reflect.Struct {
|
||||
subStruct := GetOptionsMap(field)
|
||||
for key, val := range subStruct {
|
||||
optionsMap[key] = val
|
||||
}
|
||||
} else if field.Tag.Get("comment") != "" {
|
||||
var newStr string
|
||||
optionsMap[field.Name] = &newStr
|
||||
}
|
||||
|
||||
}
|
||||
return optionsMap
|
||||
}
|
||||
|
||||
type CobraCommand struct {
|
||||
*cobra.Command
|
||||
}
|
||||
|
||||
/*
|
||||
Get all names of the fields in the given struct (recursive)
|
||||
and create a map[name of struct field]*string if the the field
|
||||
of the struct bears the comment tag.
|
||||
*/
|
||||
func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*string {
|
||||
optionsMap := make(map[string]*string)
|
||||
structVal := reflect.ValueOf(theStruct)
|
||||
structTyp := structVal.Type()
|
||||
for i := 0; i < structVal.NumField(); i++ {
|
||||
field := structTyp.Field(i)
|
||||
fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind())
|
||||
if field.Type.Kind() == reflect.Ptr {
|
||||
a := structVal.Field(i).Elem().Interface()
|
||||
subStruct := baseCmd.CreateFlags(a)
|
||||
for key, val := range subStruct {
|
||||
optionsMap[field.Name+"."+key] = val
|
||||
}
|
||||
|
||||
} else if field.Type.Kind() == reflect.Map {
|
||||
// Just check for network map
|
||||
fmt.Println(reflect.TypeOf(structVal.Field(i).Elem()))
|
||||
|
||||
} else if field.Tag.Get("comment") != "" {
|
||||
var newStr string
|
||||
optionsMap[field.Name] = &newStr
|
||||
if field.Tag.Get("sopt") != "" {
|
||||
baseCmd.PersistentFlags().StringVarP(&newStr,
|
||||
field.Tag.Get("lopt"),
|
||||
field.Tag.Get("sopt"),
|
||||
field.Tag.Get("default"),
|
||||
field.Tag.Get("comment"))
|
||||
} else {
|
||||
baseCmd.PersistentFlags().StringVar(&newStr,
|
||||
field.Tag.Get("lopt"),
|
||||
field.Tag.Get("default"),
|
||||
field.Tag.Get("comment"))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return optionsMap
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user