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/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 `}, } 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 "--" }