diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 762907bf..dc24299e 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -12,13 +12,16 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) error { - // remove the default network as the all network values are assigned + // remove the default network as all network values are assigned // to this network - if NetName != "" { + if _, ok := NodeConf.NetDevs["default"]; ok && NetName != "" { netDev := *NodeConf.NetDevs["default"] NodeConf.NetDevs[NetName] = &netDev delete(NodeConf.NetDevs, "default") - + } else { + if NodeConf.NetDevs["default"].Empty() { + delete(NodeConf.NetDevs, "default") + } } buffer, err := yaml.Marshal(NodeConf) if err != nil { diff --git a/internal/app/wwctl/node/add/main_test.go b/internal/app/wwctl/node/add/main_test.go index 29750a47..d6935790 100644 --- a/internal/app/wwctl/node/add/main_test.go +++ b/internal/app/wwctl/node/add/main_test.go @@ -2,6 +2,7 @@ package add import ( "bytes" + "fmt" "testing" "github.com/hpcng/warewulf/internal/pkg/node" @@ -14,7 +15,7 @@ func Test_Add(t *testing.T) { t.Helper() conf_yml := ` WW_INTERNAL: 0 - ` + ` nodes_yml := ` WW_INTERNAL: 43 ` @@ -33,6 +34,7 @@ WW_INTERNAL: 43 wantErr bool stdout string outDb string + flags map[string]string }{ {name: "single node add", args: []string{"n01"}, @@ -44,11 +46,50 @@ nodes: n01: profiles: - default - network devices: - default: {} `}, - {name: "double node add", - args: []string{"n0[1-2]"}, + {name: "single node add, profile foo", + args: []string{"n01"}, + flags: map[string]string{"profile": "foo"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - foo +`}, + {name: "single node add with Kernel args", + args: []string{"n01"}, + flags: map[string]string{"kernelargs": "foo"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + kernel: + args: foo + profiles: + - default +`}, + {name: "double node add explicit", + args: []string{"n01", "n02"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + n02: + profiles: + - default +`}, + {name: "single node with ipaddr", + args: []string{"n01"}, + flags: map[string]string{"ipaddr": "10.10.0.1"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -58,19 +99,111 @@ nodes: profiles: - default network devices: - default: {} + default: + ipaddr: 10.10.0.1 +`}, + {name: "three nodes with ipaddr", + args: []string{"n[01-02,03]"}, + flags: map[string]string{"ipaddr": "10.10.0.1"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + default: + ipaddr: 10.10.0.1 n02: profiles: - default network devices: - default: {} + default: + ipaddr: 10.10.0.2 + n03: + profiles: + - default + network devices: + default: + ipaddr: 10.10.0.3 +`}, + {name: "three nodes with ipaddr different network", + args: []string{"n[01-03]"}, + flags: map[string]string{"ipaddr": "10.10.0.1", "netname": "foo"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.1 + n02: + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.2 + n03: + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.3 +`}, + {name: "three nodes with ipaddr different network, with ipmiaddr", + args: []string{"n[01-03]"}, + flags: map[string]string{"ipaddr": "10.10.0.1", "netname": "foo", "ipmiaddr": "10.20.0.1"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + ipmi: + ipaddr: 10.20.0.1 + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.1 + n02: + ipmi: + ipaddr: 10.20.0.2 + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.2 + n03: + ipmi: + ipaddr: 10.20.0.3 + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.3 `}, } for _, tt := range tests { db, err = node.TestNew([]byte(nodes_yml)) assert.NoError(t, err) + fmt.Printf("Running test: %s\n", tt.name) t.Run(tt.name, func(t *testing.T) { + // store global NodeConf as the NodeConf.NetDevs["default"] will be delete + // in the main.go + tmpConfNet := NodeConf.NetDevs["default"] + //tmpConf := NodeConf + //tmpKernel := NodeConf.Kernel baseCmd.SetArgs(tt.args) + for key, val := range tt.flags { + baseCmd.Flags().Set(key, val) + } err = baseCmd.Execute() if (err != nil) != tt.wantErr { t.Errorf("Got unwanted error: %s", err) @@ -83,7 +216,15 @@ nodes: } if buf.String() != tt.stdout { t.Errorf("Got wrong output, got:'%s'\nwant:'%s'", buf.String(), tt.stdout) + return } + NodeConf.NetDevs["default"] = tmpConfNet + for key, _ := range tt.flags { + baseCmd.Flags().Set(key, "hark") + } + + //NodeConf = tmpConf + //NodeConf.Kernel = node.NewConf().Kernel }) } } diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 4ee8deca..9f89255a 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -382,3 +382,30 @@ func GetByName(node interface{}, name string) (string, error) { myEntry := entryField.Interface().(Entry) return myEntry.Get(), nil } + +/* +Check if the Netdev is empty, so has no values set +*/ +func (dev *NetDevs) Empty() bool { + if dev == nil { + return true + } + varType := reflect.TypeOf(*dev) + varVal := reflect.ValueOf(*dev) + if varVal.IsZero() { + return true + } + for i := 0; i < varType.NumField(); i++ { + if varType.Field(i).Type.Kind() == reflect.String && !varVal.Field(i).IsZero() { + val := varVal.Field(i).Interface().(string) + if val != "" { + return false + } + } else if varType.Field(i).Type == reflect.TypeOf(map[string]string{}) { + if len(varVal.Field(i).Interface().(map[string]string)) != 0 { + return false + } + } + } + return true +} diff --git a/internal/pkg/node/methods_test.go b/internal/pkg/node/methods_test.go new file mode 100644 index 00000000..d17f1529 --- /dev/null +++ b/internal/pkg/node/methods_test.go @@ -0,0 +1,32 @@ +package node + +import "testing" + +func Test_Empty(t *testing.T) { + var netdev NetDevs + var netdevPtr *NetDevs + + t.Run("test for empty", func(t *testing.T) { + if netdev.Empty() != true { + t.Errorf("netdev must be empty") + } + }) + t.Run("test for non empty", func(t *testing.T) { + netdev.Device = "foo" + if netdev.Empty() == true { + t.Errorf("netdev must be non empty") + } + }) + t.Run("test for nil pointer", func(t *testing.T) { + if netdevPtr.Empty() != true { + t.Errorf("netdev must be empty") + } + }) + t.Run("test for pointer assigned", func(t *testing.T) { + netdev.Ipaddr = "10.10.10.1" + netdevPtr = &netdev + if netdevPtr.Empty() == true { + t.Errorf("netdev must be empty") + } + }) +}