From fc80c4745ced916e7322c13d75c4cd530d044c47 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 28 Feb 2024 12:23:52 +0100 Subject: [PATCH 1/2] add various tests for `wwctl node list -a` Altough getting and setting values is correct, `wwctl list -a` will print superseded values as a list and mark them not as superseded. Tests will fail after this commit. Signed-off-by: Christian Goll --- internal/app/wwctl/node/list/main_test.go | 193 ++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/internal/app/wwctl/node/list/main_test.go b/internal/app/wwctl/node/list/main_test.go index 04c85e616..d9600cad7 100644 --- a/internal/app/wwctl/node/list/main_test.go +++ b/internal/app/wwctl/node/list/main_test.go @@ -144,6 +144,199 @@ nodes: n01: profiles: - default +`}, + { + name: "node list profile with comment", + args: []string{"-a"}, + wantErr: false, + stdout: `NODE FIELD PROFILE VALUE + n01 Id -- n01 + n01 Comment default profilecomment + n01 Ipxe -- (default) + n01 RuntimeOverlay -- (generic) + n01 SystemOverlay -- (wwinit) + n01 Root -- (initramfs) + n01 Init -- (/sbin/init) + n01 Kernel.Args -- (quiet crashkernel=no vga=791 net.naming-scheme=v238) + n01 Profiles -- default +`, + inDb: `WW_INTERNAL: 45 +nodeprofiles: + default: + comment: profilecomment +nodes: + n01: + profiles: + - default +`}, + { + name: "node list profile with comment superseded", + args: []string{"-a"}, + wantErr: false, + stdout: `NODE FIELD PROFILE VALUE + n01 Id -- n01 + n01 Comment SUPERSEDED nodecomment + n01 Ipxe -- (default) + n01 RuntimeOverlay -- (generic) + n01 SystemOverlay -- (wwinit) + n01 Root -- (initramfs) + n01 Init -- (/sbin/init) + n01 Kernel.Args -- (quiet crashkernel=no vga=791 net.naming-scheme=v238) + n01 Profiles -- default +`, + inDb: `WW_INTERNAL: 45 +nodeprofiles: + default: + comment: profilecomment +nodes: + n01: + comment: nodecomment + profiles: + - default +`}, + { + name: "node list profile with ipmi user", + args: []string{"-i"}, + wantErr: false, + stdout: `NODENAME IPMIIPADDR IPMIPORT IPMIUSERNAME IPMIINTERFACE +n01 -- -- admin -- -- +`, + inDb: `WW_INTERNAL: 45 +nodeprofiles: + default: + ipmi: + username: admin +nodes: + n01: + profiles: + - default +`}, + { + name: "node list profile with ipmi user superseded", + args: []string{"-i"}, + wantErr: false, + stdout: `NODENAME IPMIIPADDR IPMIPORT IPMIUSERNAME IPMIINTERFACE +n01 -- -- user -- -- +`, + inDb: `WW_INTERNAL: 45 +nodeprofiles: + default: + ipmi: + username: admin +nodes: + n01: + ipmi: + username: user + profiles: + - default +`}, + { + inDb: `WW_INTERNAL: 45 +nodeprofiles: + p1: {} + p2: {} +nodes: + n01: + profiles: + - p1 + - p2 +`, + name: "multiple profiles list", + args: []string{}, + wantErr: false, + stdout: ` NODE NAME PROFILES NETWORK +n01 p1,p2 +`}, + { + inDb: `WW_INTERNAL: 45 +nodeprofiles: + p1: {} + p2: {} +nodes: + n01: + profiles: + - p1 + - p2 +`, + name: "multiple profiles list all", + args: []string{"-a"}, + wantErr: false, + stdout: `NODE FIELD PROFILE VALUE +n01 Id -- n01 +n01 Ipxe -- (default) +n01 RuntimeOverlay -- (generic) +n01 SystemOverlay -- (wwinit) +n01 Root -- (initramfs) +n01 Init -- (/sbin/init) +n01 Kernel.Args -- (quiet crashkernel=no vga=791 net.naming-scheme=v238) +n01 Profiles -- p1,p2 +`}, + { + inDb: `WW_INTERNAL: 45 +nodeprofiles: + p1: + runtime overlay: + - rop1 + - rop2 +nodes: + n01: + profiles: + - p1 +`, + name: "multiple overlays list", + args: []string{"-l"}, + wantErr: false, + stdout: `NODE NAME KERNEL OVERRIDE CONTAINER OVERLAYS (S/R) +n01 -- -- (wwinit)/rop1,rop2 +`}, + { + inDb: `WW_INTERNAL: 45 +nodeprofiles: + p1: + runtime overlay: + - rop1 + - rop2 +nodes: + n01: + profiles: + - p1 + runtime overlay: + - nop1 + - ~rop1 +`, + name: "multiple overlays list", + args: []string{"-l"}, + wantErr: false, + stdout: `NODE NAME KERNEL OVERRIDE CONTAINER OVERLAYS (S/R) +n01 -- -- (wwinit)/nop1,rop2 ~{rop1} +`}, + { + inDb: `WW_INTERNAL: 45 +nodeprofiles: + p1: + runtime overlay: + - rop1 + - rop2 +nodes: + n01: + profiles: + - p1 + runtime overlay: + - nop1 + - ~rop1 +`, + name: "multiple overlays list all", + args: []string{"-a"}, + wantErr: false, + stdout: `NODE FIELD PROFILE VALUE +n01 Id -- n01 +n01 Ipxe -- (default) +n01 RuntimeOverlay SUPERSEDED nop1,rop2~{rop1} +n01 SystemOverlay -- (wwinit) +n01 Root -- (initramfs) +n01 Init -- (/sbin/init) +n01 Kernel.Args -- (quiet crashkernel=no vga=791 net.naming-scheme=v238) +n01 Profiles -- p1 `}, } From 76a40f1364ab5a272a3626f31247b95601f7f952 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 28 Feb 2024 12:26:21 +0100 Subject: [PATCH 2/2] Entry is aware if its ment as a slice or not This is needed for printing out the values, as at this part in the code there is no access to the NodeConf and only there the information if the Entry is ment as a slice or not is available. Signed-off-by: Christian Goll --- CHANGELOG.md | 1 + internal/pkg/node/datastructure.go | 1 + internal/pkg/node/methods.go | 51 ++++++++++++++++++++---------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 942104886..3f5693a65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix a rendering bug in the documentation for GRUB boot support. #1132 - Fix a locking issue with concurrent read/writes for node status. #1174 - Fix shim and grub detection for aarch64. #1145 +- wwctl [profile|node] list -a handles now slices correclty. #1113 ## 4.5.0, 2024-02-08 diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 0f4f03ca4..4907012c4 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -140,6 +140,7 @@ type Entry struct { altvalue []string from string def []string + isSlice bool } /* diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 3fd72cb63..574e3c383 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -114,6 +114,7 @@ func (ent *Entry) SetSlice(val []string) { } else if len(val) == 1 && val[0] == "" { // check also for an "empty" slice return } + ent.isSlice = true if util.InSlice(GetUnsetVerbs(), val[0]) { ent.value = []string{} } else { @@ -152,6 +153,7 @@ func (ent *Entry) SetAltSlice(val []string, from string) { if len(val) == 0 { return } + ent.isSlice = true ent.altvalue = append(ent.altvalue, val...) if ent.from == "" { ent.from = from @@ -177,11 +179,12 @@ func (ent *Entry) SetDefaultSlice(val []string) { if len(val) == 0 { return } + ent.isSlice = true ent.def = val } /* -Set default etry as bool +Set default entry as bool */ func (ent *Entry) SetDefaultB(val bool) { if val { @@ -347,26 +350,40 @@ func (ent *Entry) GetIntPtr() *int { * Misc * *********/ - /* -Returns the value of Entry if it was defined set or -alternative is presend. Default value is in '()'. If -nothing is defined '--' is returned. +Gets the the entry of the value in following order +* node value if set +* profile value if set +* default value if set */ -func (ent *Entry) Print() (ret string) { - if len(ent.value) != 0 || len(ent.altvalue) != 0 { - combList := append(ent.value, ent.altvalue...) - ret = strings.Join(cleanList(combList), ",") - if len(negList(combList)) > 0 { - ret += " ~{" + strings.Join(negList(combList), ",") + "}" +func (ent *Entry) Print() string { + if !ent.isSlice { + if len(ent.value) != 0 { + return ent.value[0] + } + if len(ent.altvalue) != 0 { + return ent.altvalue[0] + } + if len(ent.def) != 0 { + return "(" + ent.def[0] + ")" + } + } else { + var ret string + if len(ent.value) != 0 || len(ent.altvalue) != 0 { + combList := append(ent.value, ent.altvalue...) + ret = strings.Join(cleanList(combList), ",") + if len(negList(combList)) > 0 { + ret += " ~{" + strings.Join(negList(combList), ",") + "}" + } + + } + if ret != "" { + return ret + } + if len(ent.def) != 0 { + return "(" + strings.Join(ent.def, ",") + ")" } - } - if ret != "" { - return ret - } - if len(ent.def) != 0 { - return "(" + strings.Join(ent.def, ",") + ")" } return "--" }