Fix processing of UNDEF and UNSET during wwctl <node|profile> set. #1837

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-03-25 18:13:24 -06:00
parent 102916b1c8
commit 09488db3f6
8 changed files with 424 additions and 561 deletions

View File

@@ -9,179 +9,120 @@ import (
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
)
type test_description struct {
name string
args []string
wantErr bool
stdout string
inDB string
outDb string
}
func run_test(t *testing.T, test test_description) {
env := testenv.New(t)
defer env.RemoveAll()
env.WriteFile("etc/warewulf/nodes.conf", test.inDB)
warewulfd.SetNoDaemon()
name := test.name
if name == "" {
name = t.Name()
}
t.Run(name, func(t *testing.T) {
baseCmd := GetCommand()
test.args = append(test.args, "--yes")
baseCmd.SetArgs(test.args)
buf := new(bytes.Buffer)
baseCmd.SetOut(buf)
baseCmd.SetErr(buf)
err := baseCmd.Execute()
if test.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, buf.String(), test.stdout)
content := env.ReadFile("etc/warewulf/nodes.conf")
assert.YAMLEq(t, test.outDb, content)
}
})
}
func Test_Single_Node_Change_Profile(t *testing.T) {
test := test_description{
args: []string{"--profile=foo", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
func Test_Node_Set(t *testing.T) {
tests := map[string]struct {
args []string
wantErr bool
inDB string
outDB string
}{
"--profile=foo": {
args: []string{"--profile=foo", "n01"},
wantErr: false,
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- default`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- foo
`,
}
run_test(t, test)
}
func Test_Node_Unset(t *testing.T) {
test := test_description{
args: []string{"--comment=UNDEF", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
- foo`,
},
"--comment=UNDEF": {
args: []string{"--comment=UNDEF", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01:
comment: foo
profiles:
- default`,
outDb: `nodeprofiles: {}
outDB: `
nodeprofiles: {}
nodes:
n01:
profiles:
- default
`,
}
run_test(t, test)
}
func Test_Set_Ipmi_Write_Explicit(t *testing.T) {
test := test_description{
args: []string{"--ipmiwrite", "true", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
- default`,
},
"--ipmiwrite=true": {
args: []string{"--ipmiwrite", "true", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01: {}
`,
outDb: `nodeprofiles: {}
n01: {}`,
outDB: `
nodeprofiles: {}
nodes:
n01:
ipmi:
write: "true"
`,
}
run_test(t, test)
}
func Test_Set_Ipmi_Write_Implicit(t *testing.T) {
test := test_description{
args: []string{"--ipmiwrite", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
write: "true"`,
},
"--ipmiwrite": {
args: []string{"--ipmiwrite", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01: {}
`,
outDb: `nodeprofiles: {}
n01: {}`,
outDB: `
nodeprofiles: {}
nodes:
n01:
ipmi:
write: "true"
`,
}
run_test(t, test)
}
func Test_Unset_Ipmi_Write(t *testing.T) {
test := test_description{
args: []string{"--ipmiwrite=UNDEF", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
write: "true"`,
},
"--ipmiwrite=UNDEF": {
args: []string{"--ipmiwrite=UNDEF", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01:
ipmi:
write: "true"
`,
outDb: `nodeprofiles: {}
write: "true"`,
outDB: `
nodeprofiles: {}
nodes:
n01: {}
`,
}
run_test(t, test)
}
func Test_Unset_Ipmi_Write_False(t *testing.T) {
test := test_description{
args: []string{"--ipmiwrite=UNDEF", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
n01: {}`,
},
"--ipmiwrite=false": {
args: []string{"--ipmiwrite=false", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01: {}`,
outDB: `
nodeprofiles: {}
nodes:
n01:
ipmi:
write: "false"
`,
outDb: `nodeprofiles: {}
nodes:
n01: {}
`,
}
run_test(t, test)
}
func Test_Ipmi_Hidden_False(t *testing.T) {
test := test_description{
args: []string{"--ipmiwrite=false", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
write: "false"`,
},
"--ipmiwrite=false (override)": {
args: []string{"--ipmiwrite=false", "n01"},
wantErr: false,
inDB: `
nodeprofiles:
default:
ipmi:
write: "true"
nodes:
n01:
profiles:
- default
`,
outDb: `nodeprofiles:
- default`,
outDB: `
nodeprofiles:
default:
ipmi:
write: "true"
@@ -190,84 +131,66 @@ nodes:
profiles:
- default
ipmi:
write: "false"
`,
}
run_test(t, test)
}
func Test_Add_NetTags(t *testing.T) {
test := test_description{
args: []string{"--nettagadd=dns=1.1.1.1", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
write: "false"`,
},
"--nettagadd": {
args: []string{"--nettagadd=dns=1.1.1.1", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01: {}
`,
outDb: `nodeprofiles: {}
n01: {}`,
outDB: `
nodeprofiles: {}
nodes:
n01:
network devices:
default:
tags:
dns: 1.1.1.1
`,
}
run_test(t, test)
}
func Test_Del_NetTags(t *testing.T) {
test := test_description{
args: []string{"--netname=default", "--nettagdel=dns1,dns2", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles: {}
dns: 1.1.1.1`,
},
"--nettagdel": {
args: []string{"--nettagdel=dns1,dns2", "n01"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n01:
network devices:
default:
tags:
dns1: 1.1.1.1
dns2: 2.2.2.2
`,
outDb: `nodeprofiles: {}
dns2: 2.2.2.2`,
outDB: `
nodeprofiles: {}
nodes:
n01: {}
`,
}
run_test(t, test)
}
func Test_Multiple_Set_Tests(t *testing.T) {
tests := []test_description{
{
name: "single node change profile",
n01: {}`,
},
"single node change profile": {
args: []string{"--profile=foo", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- default`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- foo
`,
- foo`,
},
{
name: "multiple nodes change profile",
"multiple nodes change profile": {
args: []string{"--profile=foo", "n0[1-2]"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -277,7 +200,8 @@ nodes:
n02:
profiles:
- default`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -286,22 +210,21 @@ nodes:
- foo
n02:
profiles:
- foo
`,
- foo`,
},
{
name: "single node set ipmitag",
"single node set ipmitag": {
args: []string{"--ipmitagadd", "foo=baar", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- default`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -310,15 +233,13 @@ nodes:
- default
ipmi:
tags:
foo: baar
`,
foo: baar`,
},
{
name: "single node delete tag",
"single node delete tag": {
args: []string{"--tagdel", "tag1", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -328,7 +249,8 @@ nodes:
tags:
tag1: value1
tag2: value2`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -336,42 +258,37 @@ nodes:
profiles:
- default
tags:
tag2: value2
`,
tag2: value2`,
},
{
name: "single node add tag",
"single node add tag": {
args: []string{"--tagadd", "tag1=foobaar", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default: {}
nodes:
n01: {}
`,
outDb: `nodeprofiles:
n01: {}`,
outDB: `
nodeprofiles:
default: {}
nodes:
n01:
tags:
tag1: foobaar
`,
tag1: foobaar`,
},
{
name: "single node add tag with netdev",
"single node add tag with netdev": {
args: []string{"--tagadd", "tag1=foobaar", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default: {}
nodes:
n01:
network devices:
default:
ipaddr: 172.16.130.101
`,
outDb: `nodeprofiles:
ipaddr: 172.16.130.101`,
outDB: `
nodeprofiles:
default: {}
nodes:
n01:
@@ -379,48 +296,43 @@ nodes:
tag1: foobaar
network devices:
default:
ipaddr: 172.16.130.101
`,
ipaddr: 172.16.130.101`,
},
{
name: "single node set onboot",
"single node set onboot": {
args: []string{"--netname", "default", "--onboot=true", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default: {}
nodes:
n01:
network devices:
default:
ipaddr: 172.16.130.101`,
outDB: `
nodeprofiles:
default: {}
nodes:
n01:
network devices:
default:
ipaddr: 172.16.130.101
`,
outDb: `nodeprofiles:
default: {}
nodes:
n01:
network devices:
default:
ipaddr: 172.16.130.101
onboot: "true"
`,
onboot: "true"`,
},
{
name: "single node set fs,part and disk",
"single node set fs,part and disk": {
args: []string{"--fsname=var", "--fspath=/var", "--fsformat=btrfs", "--partname=var", "--partnumber=1", "--diskname=/dev/vda", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- default
`,
outDb: `nodeprofiles:
- default`,
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -435,15 +347,13 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
path: /var`,
},
{
name: "single delete not existing fs",
"single delete not existing fs": {
args: []string{"--fsdel=foo", "n01"},
wantErr: true,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -459,9 +369,9 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
outDb: `nodeprofiles:
path: /var`,
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -476,15 +386,13 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
path: /var`,
},
{
name: "single node delete existing fs",
"single node delete existing fs": {
args: []string{"--fsdel=/dev/disk/by-partlabel/var", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -500,9 +408,9 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
outDb: `nodeprofiles:
path: /var`,
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -513,15 +421,13 @@ nodes:
/dev/vda:
partitions:
var:
number: "1"
`,
number: "1"`,
},
{
name: "single node delete existing partition",
"single node delete existing partition": {
args: []string{"--partdel=var", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -537,9 +443,9 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
outDb: `nodeprofiles:
path: /var`,
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -551,15 +457,13 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
path: /var`,
},
{
name: "single node delete existing disk",
"single node delete existing disk": {
args: []string{"--diskdel=/dev/vda", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -574,9 +478,9 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
outDb: `nodeprofiles:
path: /var`,
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -586,22 +490,21 @@ nodes:
filesystems:
/dev/disk/by-partlabel/var:
format: btrfs
path: /var
`,
path: /var`,
},
{
name: "single node set mtu",
"single node set mtu": {
args: []string{"--mtu", "1234", "--netname=mynet", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
nodes:
n01:
profiles:
- default`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
nodes:
@@ -610,15 +513,13 @@ nodes:
- default
network devices:
mynet:
mtu: "1234"
`,
mtu: "1234"`,
},
{
name: "single node set ipmitag",
"single node set tag": {
args: []string{"--tagadd", "nodetag1=nodevalue1", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
p1:
comment: testit 1
tags:
@@ -632,7 +533,8 @@ nodes:
profiles:
- p1
- p2`,
outDb: `nodeprofiles:
outDB: `
nodeprofiles:
p1:
comment: testit 1
tags:
@@ -647,39 +549,25 @@ nodes:
- p1
- p2
tags:
nodetag1: nodevalue1
`,
nodetag1: nodevalue1`,
},
{
name: "single node set comma in comment",
"single node set comma in comment": {
args: []string{"n01", "--comment", "This is a , comment"},
wantErr: false,
stdout: "",
inDB: `nodes:
n01:
comment: old comment
`,
outDb: `nodeprofiles: {}
comment: old comment`,
outDB: `
nodeprofiles: {}
nodes:
n01:
comment: This is a , comment
`,
comment: This is a , comment`,
},
}
warewulfd.SetNoDaemon()
for _, tt := range tests {
run_test(t, tt)
}
}
func Test_Node_Add(t *testing.T) {
tests := []test_description{
{
"--tagadd (one)": {
args: []string{"--tagadd=email=node", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
inDB: `
nodeprofiles:
default:
comment: testit
tags:
@@ -688,24 +576,8 @@ nodes:
n01:
profiles:
- default`,
outDb: `nodeprofiles:
default:
comment: testit
tags:
email: profile
nodes:
n01:
profiles:
- default
tags:
email: node
`,
},
{
args: []string{"--tagadd=newtag=newval", "n01"},
wantErr: false,
stdout: "",
inDB: `nodeprofiles:
outDB: `
nodeprofiles:
default:
comment: testit
tags:
@@ -716,7 +588,24 @@ nodes:
- default
tags:
email: node`,
outDb: `nodeprofiles:
},
"--tagadd (second)": {
args: []string{"--tagadd=newtag=newval", "n01"},
wantErr: false,
inDB: `
nodeprofiles:
default:
comment: testit
tags:
email: profile
nodes:
n01:
profiles:
- default
tags:
email: node`,
outDB: `
nodeprofiles:
default:
comment: testit
tags:
@@ -727,12 +616,72 @@ nodes:
- default
tags:
email: node
newtag: newval
`,
newtag: newval`,
},
"--image=UNDEF": {
args: []string{"--image=UNDEF", "n1"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n1:
image: rockylinux-9`,
outDB: `
nodeprofiles: {}
nodes:
n1: {}`,
},
"--image=UNSET": {
args: []string{"--image=UNSET", "n1"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n1:
image: rockylinux-9`,
outDB: `
nodeprofiles: {}
nodes:
n1: {}`,
},
"--ipaddr=0.0.0.0 (unset)": {
args: []string{"--ipaddr=0.0.0.0", "n1"},
wantErr: false,
inDB: `
nodeprofiles: {}
nodes:
n1:
network devices:
default:
ipadddr: 192.168.0.1`,
outDB: `
nodeprofiles: {}
nodes:
n1: {}`,
},
}
for _, tt := range tests {
run_test(t, tt)
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
env := testenv.New(t)
defer env.RemoveAll()
env.WriteFile("etc/warewulf/nodes.conf", tt.inDB)
warewulfd.SetNoDaemon()
baseCmd := GetCommand()
args := append(tt.args, "--yes")
baseCmd.SetArgs(args)
buf := new(bytes.Buffer)
baseCmd.SetOut(buf)
baseCmd.SetErr(buf)
err := baseCmd.Execute()
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
content := env.ReadFile("etc/warewulf/nodes.conf")
assert.YAMLEq(t, tt.outDB, content)
}
})
}
}