Files
warewulf/internal/pkg/node/list.go
Christian Goll 342236b9b9 updated test for yaml/v3
Signed-off-by: Christian Goll <cgoll@suse.com>
2024-10-17 15:30:54 -04:00

153 lines
4.3 KiB
Go

package node
import (
"net"
"reflect"
"sort"
"strconv"
"strings"
)
/*
struct to hold the fields of GetFields
*/
type NodeFields struct {
Field string
Source string
Value string
}
func (f *NodeFields) Set(src, val string) {
if val == "" {
return
}
if f.Value == "" {
f.Value = val
f.Source = src
} else if f.Source != "" {
f.Value = val
if src == "" {
f.Source = "SUPERSEDED"
} else {
f.Source = src
}
}
}
type fieldMap map[string]*NodeFields
/*
Get all the info out of NodeConf. If emptyFields is set true, all fields are shown not only the ones with effective values
*/
func (nodeYml *NodeYaml) GetFields(node NodeConf) (output []NodeFields) {
nodeMap := make(fieldMap)
for _, p := range node.Profiles {
if profile, ok := nodeYml.nodeProfiles[p]; ok {
nodeMap.recursiveFields(profile, "", p)
}
}
rawNode, _ := nodeYml.GetNodeOnlyPtr(node.id)
nodeMap.recursiveFields(rawNode, "", "")
for _, elem := range nodeMap {
if elem.Value != "" {
output = append(output, *elem)
}
}
sort.Slice(output, func(i, j int) bool {
return output[i].Field < output[j].Field
})
return output
}
/*
Get all the info out of ProfileConf. If emptyFields is set true, all fields are shown not only the ones with effective values
*/
func (nodeYml *NodeYaml) GetFieldsProfile(profile ProfileConf) (output []NodeFields) {
profileMap := make(fieldMap)
profileMap.recursiveFields(&profile, "", "")
for _, elem := range profileMap {
if elem.Value != "" {
output = append(output, *elem)
}
}
sort.Slice(output, func(i, j int) bool {
return output[i].Field < output[j].Field
})
return output
}
/*
Internal function which travels through all fields of a NodeConf and for this
reason needs to be called via interface{}
*/
func (fieldMap fieldMap) recursiveFields(obj interface{}, prefix string, source string) {
valObj := reflect.ValueOf(obj)
typeObj := reflect.TypeOf(obj)
if valObj.IsNil() {
return
}
for i := 0; i < typeObj.Elem().NumField(); i++ {
if valObj.Elem().Field(i).IsValid() {
if !typeObj.Elem().Field(i).IsExported() {
continue
}
switch typeObj.Elem().Field(i).Type.Kind() {
case reflect.Map:
mapIter := valObj.Elem().Field(i).MapRange()
for mapIter.Next() {
fieldMap.recursiveFields(mapIter.Value().Interface(), prefix+typeObj.Elem().Field(i).Name+"["+mapIter.Key().String()+"].", source)
}
if valObj.Elem().Field(i).Len() == 0 {
fieldMap[prefix+typeObj.Elem().Field(i).Name] = &NodeFields{
Field: prefix + typeObj.Elem().Field(i).Name + "[]",
}
}
case reflect.Struct:
fieldMap.recursiveFields(valObj.Elem().Field(i).Addr().Interface(), "", source)
case reflect.Ptr:
if valObj.Elem().Field(i).Addr().IsValid() {
fieldMap.recursiveFields(valObj.Elem().Field(i).Interface(), prefix+typeObj.Elem().Field(i).Name+".", source)
}
default:
if _, ok := fieldMap[prefix+typeObj.Elem().Field(i).Name]; !ok {
fieldMap[prefix+typeObj.Elem().Field(i).Name] = &NodeFields{
Field: prefix + typeObj.Elem().Field(i).Name,
Source: source,
}
}
switch typeObj.Elem().Field(i).Type {
case reflect.TypeOf([]string{}):
vals := (valObj.Elem().Field(i).Interface()).([]string)
fieldMap[prefix+typeObj.Elem().Field(i).Name] = &NodeFields{
Field: prefix + typeObj.Elem().Field(i).Name,
Source: source,
Value: strings.Join(vals, ","),
}
case reflect.TypeOf(net.IP{}):
val := (valObj.Elem().Field(i).Interface()).(net.IP)
if val != nil {
fieldMap[prefix+typeObj.Elem().Field(i).Name].Set(source, val.String())
}
case reflect.TypeOf(net.IPMask{}):
val := (valObj.Elem().Field(i).Interface()).(net.IPMask)
if val != nil {
fieldMap[prefix+typeObj.Elem().Field(i).Name].Set(source, val.String())
}
case reflect.TypeOf(true):
val := (valObj.Elem().Field(i).Interface()).(bool)
if val {
fieldMap[prefix+typeObj.Elem().Field(i).Name].Set(source, strconv.FormatBool(val))
}
default:
fieldMap[prefix+typeObj.Elem().Field(i).Name].Set(source, valObj.Elem().Field(i).String())
}
} /*else if typeObj.Elem().Field(i).Type.Kind() == reflect.Ptr {
fieldMap.recursiveFields(valObj.Elem().Field(i).Interface(), emptyFields, prefix+typeObj.Elem().Field(i).Name+".", source)
}*/
}
}
}