use netParseIP and ParseMAC

check also MAC addresses and common formating

Signed-off-by: Christian Goll <cgoll@suse.de>

reformat ipaddr for test coverage

fixed processing of default values

updated transformer tests

correct behavior for tags

add tests for tags

new tests for primary network

Signed-off-by: Christian Goll <cgoll@suse.de>
This commit is contained in:
Christian Goll
2023-02-07 09:16:55 +01:00
parent c14dd3c6d1
commit b0602133ec
15 changed files with 335 additions and 76 deletions

View File

@@ -9,7 +9,6 @@ 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
@@ -17,10 +16,12 @@ 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()
}
// run converters for different types
for _, c := range vars.converters {
if err := c(); err != nil {
return err
}
}
// remove the default network as all network values are assigned
// to this network
if _, ok := vars.nodeConf.NetDevs["default"]; ok && vars.netName != "" {

View File

@@ -14,7 +14,7 @@ import (
type variables struct {
netName string
nodeConf node.NodeConf
converters []func()
converters []func() error
}
// Returns the newly created command

View File

@@ -15,7 +15,9 @@ import (
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
// run converters for different types
for _, c := range Converters {
c()
if err := c(); err != nil {
return err
}
}
// remove the default network as the all network values are assigned
// to this network

View File

@@ -38,7 +38,7 @@ var (
SetYes bool
SetForce bool
NodeConf node.NodeConf
Converters []func()
Converters []func() error
)
func init() {

View File

@@ -16,7 +16,9 @@ import (
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
// run converters for different types
for _, c := range Converters {
c()
if err := c(); err != nil {
return err
}
}
// remove the default network as the all network values are assigned
// to this network

View File

@@ -25,7 +25,7 @@ var (
SetForce bool
NetName string
ProfileConf node.NodeConf
Converters []func()
Converters []func() error
)
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -38,7 +38,7 @@ var (
SetForce bool
NetName string
ProfileConf node.NodeConf
Converters []func()
Converters []func() error
)
func init() {

View File

@@ -2,7 +2,7 @@ package node
import (
"fmt"
"net/netip"
"net"
"reflect"
"strconv"
"strings"
@@ -18,9 +18,11 @@ func (nodeConf *NodeConf) Check() (err error) {
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"))
newFmt, 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 newFmt != "" {
nodeInfoVal.Elem().Field(i).SetString(newFmt)
}
} else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !nodeInfoVal.Elem().Field(i).IsNil() {
nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface())
@@ -28,9 +30,11 @@ func (nodeConf *NodeConf) Check() (err error) {
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"))
newFmt, 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 newFmt != "" {
nestVal.Elem().Field(j).SetString(newFmt)
}
}
}
@@ -40,9 +44,11 @@ func (nodeConf *NodeConf) Check() (err error) {
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"))
newFmt, 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)
} else if newFmt != "" {
netVal.Elem().Field(j).SetString(newFmt)
}
}
}
@@ -51,26 +57,39 @@ func (nodeConf *NodeConf) Check() (err error) {
return nil
}
func checker(value string, valType string) (err error) {
func checker(value string, valType string) (niceValue string, err error) {
if valType == "" || value == "" {
return nil
return "", nil
}
//wwlog.Debug("checker: %s is %s", value, valType)
switch valType {
case "":
return nil
return "", nil
case "bool":
if strings.ToLower(value) == "yes" {
return nil
return "true", nil
}
if strings.ToLower(value) == "no" {
return nil
return "false", nil
}
_, err = strconv.ParseBool(value)
return err
myBool, err := strconv.ParseBool(value)
return strconv.FormatBool(myBool), err
case "IP":
_, err = netip.ParseAddr(value)
return err
if addr := net.ParseIP(value); addr == nil {
return "", fmt.Errorf("%s can't be parsed to ip address", value)
} else {
return addr.String(), nil
}
case "MAC":
if mac, err := net.ParseMAC(value); err != nil {
return "", fmt.Errorf("%s can't be parsed to MAC address: %s", value, err)
} else {
return mac.String(), nil
}
case "uint":
if _, err := strconv.ParseUint(value, 10, 64); err != nil {
return "", fmt.Errorf("%s is not a uint: %s", value, err)
}
}
return nil
return "", nil
}

View File

@@ -135,12 +135,13 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) {
defData, err := os.ReadFile(DefaultConfig)
if err != nil {
wwlog.Verbose("Couldn't read DefaultConfig :%s\n", err)
wwlog.Verbose("Using building defaults")
defData = []byte(FallBackConf)
}
wwlog.Debug("Unmarshalling default config\n")
err = yaml.Unmarshal(defData, &defConf)
if err != nil {
wwlog.Verbose("Couldn't unmarshall defaults from file :%s\n", err)
wwlog.Verbose("Using building defaults")
err = yaml.Unmarshal([]byte(FallBackConf), &defConf)
if err != nil {
wwlog.Warn("Could not get any defaults")

View File

@@ -75,14 +75,14 @@ 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 (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"`
Hwaddr string `yaml:"hwaddr,omitempty" lopt:"hwaddr" sopt:"H" comment:"Set the device's HW address for given network" type:"MAC"`
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" type:"IP"`
Prefix string `yaml:"prefix,omitempty"`
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"`
MTU string `yaml:"mtu,omitempty" lopt:"mtu" comment:"Set the mtu" type:"uint"`
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"`

View File

@@ -1,14 +1,13 @@
package node
import (
"fmt"
"net"
"os"
"reflect"
"strconv"
"strings"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
)
@@ -17,7 +16,7 @@ Create cmd line flags from the NodeConf fields. Returns a []func() where every f
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()) {
func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) (converters []func() error) {
nodeInfoType := reflect.TypeOf(nodeConf)
nodeInfoVal := reflect.ValueOf(nodeConf)
// now iterate of every field
@@ -60,48 +59,54 @@ func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []stri
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()) {
myType reflect.StructField, myVal *reflect.Value) (converters []func() error) {
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) })
converters = append(converters, func() error {
if !util.InSlice(GetUnsetVerbs(), *ptr) && *ptr != "" {
_, err := strconv.ParseUint(myType.Tag.Get(*ptr), 10, 32)
if err != nil {
return err
}
}
return nil
})
if myType.Tag.Get("sopt") != "" {
baseCmd.PersistentFlags().UintVarP(&valueRaw,
baseCmd.PersistentFlags().StringVarP(ptr,
myType.Tag.Get("lopt"),
myType.Tag.Get("sopt"),
uint(defaultConv),
myType.Tag.Get("default"),
myType.Tag.Get("comment"))
} else {
baseCmd.PersistentFlags().UintVar(&valueRaw,
baseCmd.PersistentFlags().StringVar(ptr,
myType.Tag.Get("lopt"),
uint(defaultConv),
myType.Tag.Get("default"),
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() {
converters = append(converters, func() error {
if !util.InSlice(GetUnsetVerbs(), *ptr) && *ptr != "" {
if strings.ToLower(*ptr) != "yes" {
*ptr = "true"
return
return nil
}
if strings.ToLower(*ptr) != "no" {
*ptr = "false"
return
return nil
}
val, err := strconv.ParseBool(*ptr)
if err != nil {
wwlog.Error("commandline option %s needs to be bool", myType.Tag.Get("lopt"))
os.Exit(1)
return fmt.Errorf("commandline option %s needs to be bool", myType.Tag.Get("lopt"))
}
*ptr = strconv.FormatBool(val)
}
return nil
})
if myType.Tag.Get("sopt") != "" {
baseCmd.PersistentFlags().StringVarP(ptr,
@@ -119,10 +124,12 @@ func createFlags(baseCmd *cobra.Command, excludeList []string,
case "IP":
defaultConv := net.ParseIP(myType.Tag.Get("default"))
var valueRaw net.IP
converters = append(converters, func() {
converters = append(converters, func() error {
if valueRaw != nil {
// will always get a IP, not a string
*ptr = valueRaw.String()
}
return nil
})
if myType.Tag.Get("sopt") != "" {
baseCmd.PersistentFlags().IPVarP(&valueRaw,
@@ -139,7 +146,14 @@ func createFlags(baseCmd *cobra.Command, excludeList []string,
case "IPMask":
defaultConv := net.ParseIP(myType.Tag.Get("default")).DefaultMask()
var valueRaw net.IPMask
converters = append(converters, func() { *ptr = valueRaw.String() })
converters = append(converters, func() error {
if valueRaw != nil {
*ptr = valueRaw.String()
return nil
} else {
return fmt.Errorf("could not parse %s to IP", valueRaw.String())
}
})
if myType.Tag.Get("sopt") != "" {
baseCmd.PersistentFlags().IPMaskVarP(&valueRaw,
myType.Tag.Get("lopt"),
@@ -152,6 +166,27 @@ func createFlags(baseCmd *cobra.Command, excludeList []string,
defaultConv,
myType.Tag.Get("comment"))
}
case "MAC":
converters = append(converters, func() error {
myMac, err := net.ParseMAC(*ptr)
if err != nil {
return err
}
*ptr = myMac.String()
return nil
})
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"))
}
default:
if myType.Tag.Get("sopt") != "" {
baseCmd.PersistentFlags().StringVarP(ptr,

View File

@@ -1,37 +1,223 @@
package node
import (
"fmt"
"reflect"
"strconv"
"testing"
"gopkg.in/yaml.v2"
)
func NewTransformerTestNode() NodeYaml {
var data = `
nodeprofiles:
default:
comment: This profile is automatically included for each node
ipmi:
username: greg
profile2:
tags:
foo: foo profile2
comment: Comment profile2
ipmi:
tags:
foo: foo ipmi profile
nodes:
test_node1:
comment: Node Comment
profiles:
- default
network devices:
net0:
device: eth1
discoverable: true
ipmi:
username: chris
tags:
baar: baar node1
test_node2:
primary: net0
profiles:
- default
- profile2
network devices:
net0:
netmask: 1.1.1.1
net1:
ipaddr: 1.2.3.4
tags:
baar: baar node2
test_node3:
profiles:
- profile2
tags:
foo: foo node3
foobaar: foobaar node3
ipmi:
ipaddr: 1.1.1.1
tags:
foo: foo ipmi node3
`
var ret NodeYaml
_ = yaml.Unmarshal([]byte(data), &ret)
return ret
}
func Test_nodeYaml_SetFrom(t *testing.T) {
c, _ := NewTestNode()
singleNodeConf := c.Nodes["test_node"]
singleNodeInfo := NewInfo()
singleNodeInfo.SetFrom(singleNodeConf)
tests := []struct {
c := NewTransformerTestNode()
nodes, _ := c.FindAllNodes()
test_node1 := NewInfo()
test_node2 := NewInfo()
test_node3 := NewInfo()
for _, n := range nodes {
if n.Id.Get() == "test_node1" {
test_node1 = n
}
if n.Id.Get() == "test_node2" {
test_node2 = n
}
if n.Id.Get() == "test_node3" {
test_node3 = n
}
}
getByNametests := []struct {
name string
arg string
want string
wantErr bool
}{
{"Right comment", "Comment", "Node Comment", false},
{"FieldName", "comment", "NodeComment", true},
{"GetByName: FieldValue", "Comment", "Node Comment", false},
{"GetByName: FieldName", "comment", "NodeComment", true},
}
for _, tt := range tests {
for _, tt := range getByNametests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetByName(&singleNodeInfo, tt.arg)
got, err := GetByName(&test_node1, tt.arg)
if (err != nil) != tt.wantErr {
t.Errorf("GetByName(%s,%s) error = %v, wantErr %v",
reflect.TypeOf(singleNodeConf), tt.arg, err, tt.wantErr)
reflect.TypeOf(test_node1), tt.arg, err, tt.wantErr)
return
}
if (got != tt.want) != tt.wantErr {
t.Errorf("GetByName(%s,%s) got = %v, want = %v",
reflect.TypeOf(singleNodeConf), tt.arg, got, tt.want)
reflect.TypeOf(test_node1), tt.arg, got, tt.want)
return
}
})
}
t.Run("Get() comment", func(t *testing.T) {
comment := test_node1.Comment.Get()
if comment != "Node Comment" {
t.Errorf("Get() returned wrong comment: %s", comment)
}
})
t.Run("Get() profile comment", func(t *testing.T) {
comment := test_node2.Comment.Get()
if comment != "Comment profile2" {
t.Errorf("Get() returned wrong comment: %s", comment)
}
})
t.Run("Get() default ipxe", func(t *testing.T) {
value := test_node1.Ipxe.Get()
if value != "default" {
t.Errorf("Get() returned wrong ipxe template: %s", value)
}
})
t.Run("GetSlice() default profile", func(t *testing.T) {
value := test_node1.Profiles.GetSlice()[0]
if value != "default" {
t.Errorf("GetSlice() returned wrong profile: %s", value)
}
})
t.Run("Get() default kernel args", func(t *testing.T) {
value := test_node1.Kernel.Args.Get()
if value != "quiet crashkernel=no vga=791 net.naming-scheme=v238" {
t.Errorf("Get() returned wrong kernel args: %s", value)
}
})
t.Run("Get() default network mask", func(t *testing.T) {
value := test_node1.NetDevs["net0"].Netmask.Get()
if value != "255.255.255.0" {
t.Errorf("Get() returned wrong default netmask: %s", value)
}
})
t.Run("Get() default network mask", func(t *testing.T) {
value := test_node2.NetDevs["net0"].Netmask.Get()
if value != "1.1.1.1" {
t.Errorf("Get() returned wrong default netmask: %s", value)
}
})
t.Run("GetB() primary for single network", func(t *testing.T) {
value := test_node1.NetDevs["net0"].Primary.GetB()
if !value {
t.Errorf("GetB() returned wrong: %s", strconv.FormatBool(value))
}
})
t.Run("GetB() for primary with two networks", func(t *testing.T) {
value := test_node2.NetDevs["net0"].Primary.GetB()
if !value {
t.Errorf("GetB() returned wrong: %s", strconv.FormatBool(value))
}
})
t.Run("GetB() for primary with two networks, get secondary network", func(t *testing.T) {
value := test_node2.NetDevs["net1"].Primary.GetB()
if value {
t.Errorf("GetB() returned wrong: %s", strconv.FormatBool(value))
}
})
t.Run("GetB() default discoverable", func(t *testing.T) {
value := test_node1.Discoverable.GetB()
if !value {
t.Errorf("GetB() returned wrong: %s", strconv.FormatBool(value))
}
})
t.Run("GetB() default discoverable", func(t *testing.T) {
value := test_node2.Discoverable.GetB()
if value {
t.Errorf("GetB() returned wrong: %s", strconv.FormatBool(value))
}
})
t.Run("Get() ipmi user from profile", func(t *testing.T) {
value := test_node2.Ipmi.UserName.Get()
if value != "greg" {
t.Errorf("Get() returned wrong ipmi username: %s", value)
}
})
t.Run("Get() ipmi user from node", func(t *testing.T) {
value := test_node1.Ipmi.UserName.Get()
if value != "chris" {
t.Errorf("Get() returned wrong ipmi username: %s", value)
}
})
t.Run("Get() tag foo from profile, node does not have this tag", func(t *testing.T) {
value := test_node2.Tags["foo"].Get()
if value != "foo profile2" {
t.Errorf("Get() returned wrong tag for foo: %s", value)
}
})
t.Run("Get() tag baar from node, node tag map is not overwritten", func(t *testing.T) {
value := test_node2.Tags["baar"].Get()
if value != "baar node2" {
t.Errorf("Get() returned wrong tag for foo: %s", value)
}
})
t.Run("Get() tag foo from node, tag present in profile", func(t *testing.T) {
value := test_node3.Tags["foo"].Get()
if value != "foo node3" {
t.Errorf("Get() returned wrong tag for foo: %s", value)
}
})
t.Run("Get() tag foobaar from node", func(t *testing.T) {
value := test_node3.Tags["foobaar"].Get()
if value != "foobaar node3" {
t.Errorf("Get() returned wrong tag for foo: %s", value)
}
})
t.Run("Get() ipmitag foo from profile, node does not have this tag", func(t *testing.T) {
fmt.Println("ipmi tags", test_node3.Ipmi.Tags)
fmt.Println(c.Nodes["test_node3"].Ipmi)
value := test_node3.Ipmi.Tags["foo"].Get()
if value != "foo ipmi node3" {
t.Errorf("Get() returned wrong tag for foo: %s", value)
}
})
}

View File

@@ -266,24 +266,28 @@ func (node *NodeInfo) setterFrom(n *NodeConf, nameArg string,
}
} else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() {
nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface())
netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface())
nestedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface())
nestedConfVal := reflect.ValueOf(valField.Interface())
for j := 0; j < nestedInfoType.Elem().NumField(); j++ {
nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name)
if nestedVal.IsValid() {
if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) {
setter(netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry), nestedVal.String(), nameArg)
} else {
if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) {
setter(nestedInfoVal.Elem().Field(j).Addr().Interface().(*Entry), nestedVal.String(), nameArg)
} else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string](*Entry){}) {
confMap := nestedVal.Interface().(map[string]string)
if netstedInfoVal.Elem().Field(j).IsNil() {
newMap := make(map[string]*Entry)
mapPtr := (netstedInfoVal.Elem().Field(j).Addr().Interface()).(*map[string](*Entry))
*mapPtr = newMap
if nestedInfoVal.Elem().Field(j).IsNil() {
ptr := nestedInfoVal.Elem().Field(j).Addr().Interface().(*map[string](*Entry))
*ptr = make(map[string]*Entry)
}
tagMap := nestedInfoVal.Elem().Field(j).Interface().(map[string](*Entry))
for key, val := range confMap {
entr := new(Entry)
setter(entr, val, nameArg)
(netstedInfoVal.Elem().Field(j).Interface()).(map[string](*Entry))[key] = entr
if entr, ok := tagMap[key]; ok {
setter(entr, val, nameArg)
} else {
entr := new(Entry)
tagMap[key] = entr
setter(entr, val, nameArg)
}
}
}
}
@@ -291,9 +295,17 @@ func (node *NodeInfo) setterFrom(n *NodeConf, nameArg string,
} else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) {
confMap := valField.Interface().(map[string]string)
for key, val := range confMap {
entr := new(Entry)
setter(entr, val, nameArg)
(nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = entr
tagMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*Entry))
if nodeInfoVal.Elem().Field(i).IsNil() {
tagMap = make(map[string]*Entry)
}
if entr, ok := tagMap[key]; ok {
setter(entr, val, nameArg)
} else {
entr := new(Entry)
tagMap[key] = entr
setter(entr, val, nameArg)
}
}
} else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) {
netValMap := valField.Interface().(map[string](*NetDevs))

View File

@@ -27,10 +27,11 @@ func (config *NodeYaml) FindByHwaddr(hwa string) (NodeInfo, error) {
}
func (config *NodeYaml) FindByIpaddr(ipaddr string) (NodeInfo, error) {
if net.ParseIP(ipaddr) == nil {
if addr := net.ParseIP(ipaddr); addr == nil {
return NodeInfo{}, errors.New("invalid IP:" + ipaddr)
} else {
ipaddr = addr.String()
}
var ret NodeInfo
n, _ := config.FindAllNodes()

View File

@@ -6,7 +6,7 @@ import (
"gopkg.in/yaml.v2"
)
func NewTestNode() (NodeYaml, error) {
func NewUtilTestNode() (NodeYaml, error) {
var data = `
nodeprofiles:
default:
@@ -49,7 +49,7 @@ nodes:
}
func Test_nodeYaml_FindByHwaddr(t *testing.T) {
c, _ := NewTestNode()
c, _ := NewUtilTestNode()
//type fields struct {
// NodeProfiles map[string]*NodeConf
// Nodes map[string]*NodeConf
@@ -90,7 +90,7 @@ func Test_nodeYaml_FindByHwaddr(t *testing.T) {
}
func Test_nodeYaml_FindByIpaddr(t *testing.T) {
c, _ := NewTestNode()
c, _ := NewUtilTestNode()
type args struct {
ipaddr string
}