check the yaml direclty after unmarshalling

This commit is contained in:
Christian Goll
2023-02-06 17:00:24 +01:00
parent 13bc378a6b
commit c14dd3c6d1
7 changed files with 176 additions and 31 deletions

View File

@@ -0,0 +1,76 @@
package node
import (
"fmt"
"net/netip"
"reflect"
"strconv"
"strings"
)
/*
Checks if for NodeConf all values can be parsed according to their type.
*/
func (nodeConf *NodeConf) Check() (err error) {
nodeInfoType := reflect.TypeOf(nodeConf)
nodeInfoVal := reflect.ValueOf(nodeConf)
// now iterate of every field
for i := 0; i < nodeInfoVal.Elem().NumField(); i++ {
//wwlog.Debug("checking field: %s type: %s", nodeInfoType.Elem().Field(i).Name, nodeInfoVal.Elem().Field(i).Type())
if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.String {
err = checker(nodeInfoVal.Elem().Field(i).Interface().(string), nodeInfoType.Elem().Field(i).Tag.Get("type"))
if err != nil {
return fmt.Errorf("field: %s value:%s err: %s", nodeInfoType.Elem().Field(i).Name, nodeInfoVal.Elem().Field(i).String(), err)
}
} else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !nodeInfoVal.Elem().Field(i).IsNil() {
nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface())
nestVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface())
for j := 0; j < nestType.Elem().NumField(); j++ {
if nestType.Elem().Field(j).Type.Kind() == reflect.String {
//wwlog.Debug("checking field: %s type: %s", nestType.Elem().Field(j).Name, nestType.Elem().Field(j).Tag.Get("type"))
err = checker(nestVal.Elem().Field(j).Interface().(string), nestType.Elem().Field(j).Tag.Get("type"))
if err != nil {
return fmt.Errorf("field: %s value:%s err: %s", nestType.Elem().Field(j).Name, nestVal.Elem().Field(j).String(), err)
}
}
}
} else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) {
netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs)
for _, val := range netMap {
netType := reflect.TypeOf(val)
netVal := reflect.ValueOf(val)
for j := 0; j < netType.Elem().NumField(); j++ {
err = checker(netVal.Elem().Field(j).String(), netType.Elem().Field(j).Tag.Get("type"))
if err != nil {
return fmt.Errorf("field: %s value:%s err: %s", netType.Elem().Field(j).Name, netVal.Elem().Field(j).String(), err)
}
}
}
}
}
return nil
}
func checker(value string, valType string) (err error) {
if valType == "" || value == "" {
return nil
}
//wwlog.Debug("checker: %s is %s", value, valType)
switch valType {
case "":
return nil
case "bool":
if strings.ToLower(value) == "yes" {
return nil
}
if strings.ToLower(value) == "no" {
return nil
}
_, err = strconv.ParseBool(value)
return err
case "IP":
_, err = netip.ParseAddr(value)
return err
}
return nil
}

View File

@@ -2,6 +2,7 @@ package node
import (
"errors"
"fmt"
"os"
"path"
"sort"
@@ -71,6 +72,21 @@ func New() (NodeYaml, error) {
if err != nil {
return ret, err
}
wwlog.Debug("Checking nodes for types")
for nodeName, node := range ret.Nodes {
err = node.Check()
if err != nil {
wwlog.Warn("node: %s parsing error: %s", nodeName, err)
return ret, err
}
}
for profileName, profile := range ret.NodeProfiles {
err = profile.Check()
if err != nil {
wwlog.Warn("node: %s parsing error: %s", profileName, err)
return ret, err
}
}
wwlog.Debug("Returning node object")
cachedDB = ret
@@ -165,6 +181,10 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
node.Tags[keyname] = key
delete(node.Keys, keyname)
}
err = node.Check()
if err != nil {
return nil, fmt.Errorf("node: %s check error: %s", nodename, err)
}
n.SetFrom(node)
// only now the netdevs start to exist so that default values can be set
for _, netdev := range n.NetDevs {

View File

@@ -13,7 +13,9 @@ import (
)
/*
Create cmd line flags from the NodeConf fields
Create cmd line flags from the NodeConf fields. Returns a []func() where every function
must be called, as the commandline parser returns e.g. netip.IP objects which must be parsedf
back to strings.
*/
func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) (converters []func()) {
nodeInfoType := reflect.TypeOf(nodeConf)