diff --git a/CHANGELOG.md b/CHANGELOG.md index fbc637af..1dda5204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Return non-zero exit code on overlay build failure #1393 - Return non-zero exit code on container copy failure #1377 - Return non-zero exit code on container sub-commands #1414 +- Fix excessive line spacing issue when listing nodes. #1241 ## v4.5.8, unreleased diff --git a/internal/app/wwctl/container/list/main.go b/internal/app/wwctl/container/list/main.go index 8f7bb788..e94d88a5 100644 --- a/internal/app/wwctl/container/list/main.go +++ b/internal/app/wwctl/container/list/main.go @@ -9,6 +9,7 @@ import ( apicontainer "github.com/warewulf/warewulf/internal/pkg/api/container" "github.com/warewulf/warewulf/internal/pkg/container" "github.com/warewulf/warewulf/internal/pkg/util" + "github.com/warewulf/warewulf/internal/pkg/wwlog" ) var containerList = apicontainer.ContainerList @@ -22,7 +23,7 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err return err } if vars.full { - ph := helper.NewPrintHelper([]string{"CONTAINER NAME", "NODES", "KERNEL VERSION", "CREATION TIME", "MODIFICATION TIME", "SIZE"}) + ph := helper.New([]string{"CONTAINER NAME", "NODES", "KERNEL VERSION", "CREATION TIME", "MODIFICATION TIME", "SIZE"}) for i := 0; i < len(containerInfo); i++ { createTime := time.Unix(int64(containerInfo[i].CreateDate), 0) modTime := time.Unix(int64(containerInfo[i].ModDate), 0) @@ -43,8 +44,9 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err }) } ph.Render() + wwlog.Info(ph.String()) } else if vars.kernel { - ph := helper.NewPrintHelper([]string{"CONTAINER NAME", "NODES", "KERNEL VERSION"}) + ph := helper.New([]string{"CONTAINER NAME", "NODES", "KERNEL VERSION"}) for i := 0; i < len(containerInfo); i++ { ph.Append([]string{ containerInfo[i].Name, @@ -53,9 +55,9 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err }) } ph.Render() - + wwlog.Info(ph.String()) } else if showSize { - ph := helper.NewPrintHelper([]string{"CONTAINER NAME", "NODES", "SIZE"}) + ph := helper.New([]string{"CONTAINER NAME", "NODES", "SIZE"}) for i := 0; i < len(containerInfo); i++ { sz := util.ByteToString(int64(containerInfo[i].ImgSize)) if vars.compressed { @@ -72,15 +74,16 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err }) } ph.Render() - + wwlog.Info(ph.String()) } } else { - ph := helper.NewPrintHelper([]string{"CONTAINER NAME"}) + ph := helper.New([]string{"CONTAINER NAME"}) list, _ := container.ListSources() for _, cont := range list { ph.Append([]string{cont}) } ph.Render() + wwlog.Info(ph.String()) } return } diff --git a/internal/app/wwctl/container/list/main_test.go b/internal/app/wwctl/container/list/main_test.go index 74b06584..b1f44e14 100644 --- a/internal/app/wwctl/container/list/main_test.go +++ b/internal/app/wwctl/container/list/main_test.go @@ -13,6 +13,7 @@ import ( warewulfconf "github.com/warewulf/warewulf/internal/pkg/config" "github.com/warewulf/warewulf/internal/pkg/node" "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" ) func Test_List(t *testing.T) { @@ -67,10 +68,11 @@ WW_INTERNAL: 0 tt.mockFunc() baseCmd := GetCommand() baseCmd.SetArgs(tt.args) - baseCmd.SetOut(nil) - baseCmd.SetErr(nil) stdoutR, stdoutW, _ := os.Pipe() os.Stdout = stdoutW + wwlog.SetLogWriter(os.Stdout) + baseCmd.SetOut(os.Stdout) + baseCmd.SetErr(os.Stdout) err = baseCmd.Execute() if err != nil { t.Errorf("Received error when running command, err: %v", err) diff --git a/internal/app/wwctl/container/rename/main_test.go b/internal/app/wwctl/container/rename/main_test.go index 2b07087f..358a2b32 100644 --- a/internal/app/wwctl/container/rename/main_test.go +++ b/internal/app/wwctl/container/rename/main_test.go @@ -11,6 +11,7 @@ import ( containerList "github.com/warewulf/warewulf/internal/app/wwctl/container/list" "github.com/warewulf/warewulf/internal/pkg/testenv" "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" ) func Test_Rename(t *testing.T) { @@ -27,8 +28,8 @@ func Test_Rename(t *testing.T) { // then rename it t.Run("container rename", func(t *testing.T) { baseCmd := GetCommand() - baseCmd.SetOut(nil) - baseCmd.SetErr(nil) + baseCmd.SetOut(os.Stdout) + baseCmd.SetErr(os.Stdout) baseCmd.SetArgs([]string{"test-container", "test-container-rename"}) err := baseCmd.Execute() assert.NoError(t, err) @@ -42,10 +43,11 @@ func Test_Rename(t *testing.T) { func verifyContainerListOutput(t *testing.T, content string) { baseCmd := containerList.GetCommand() - baseCmd.SetOut(nil) - baseCmd.SetErr(nil) stdoutR, stdoutW, _ := os.Pipe() os.Stdout = stdoutW + baseCmd.SetOut(os.Stdout) + baseCmd.SetErr(os.Stdout) + wwlog.SetLogWriter(os.Stdout) err := baseCmd.Execute() assert.NoError(t, err) diff --git a/internal/app/wwctl/helper/printhelper.go b/internal/app/wwctl/helper/printhelper.go index 2361ebd8..ada9d5fd 100644 --- a/internal/app/wwctl/helper/printhelper.go +++ b/internal/app/wwctl/helper/printhelper.go @@ -1,17 +1,20 @@ package helper import ( - "os" + "regexp" + "strings" "github.com/olekukonko/tablewriter" ) type PrintHelper struct { *tablewriter.Table + sb *strings.Builder } -func NewPrintHelper(header []string) *PrintHelper { - tb := tablewriter.NewWriter(os.Stdout) +func New(header []string) *PrintHelper { + sb := &strings.Builder{} + tb := tablewriter.NewWriter(sb) tb.SetHeader(header) tb.SetAutoWrapText(false) tb.SetHeaderAlignment(tablewriter.ALIGN_LEFT) @@ -23,5 +26,11 @@ func NewPrintHelper(header []string) *PrintHelper { tb.SetBorder(false) return &PrintHelper{ Table: tb, + sb: sb, } } + +func (p *PrintHelper) String() string { + exp := regexp.MustCompile("(?m) *$") + return string(exp.ReplaceAll([]byte(p.sb.String()), []byte(""))) +} diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index e36ae5ed..af0e5cd4 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -40,11 +40,12 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err if req.Type == wwapiv1.GetNodeList_YAML || req.Type == wwapiv1.GetNodeList_JSON { wwlog.Info(nodeInfo.Output[0]) } else { - ph := helper.NewPrintHelper(strings.Split(nodeInfo.Output[0], ":=:")) + ph := helper.New(strings.Split(nodeInfo.Output[0], ":=:")) for _, val := range nodeInfo.Output[1:] { ph.Append(strings.Split(val, ":=:")) } ph.Render() + wwlog.Info(ph.String()) } } return diff --git a/internal/app/wwctl/node/list/main_test.go b/internal/app/wwctl/node/list/main_test.go index 2d043e4f..58ef36bf 100644 --- a/internal/app/wwctl/node/list/main_test.go +++ b/internal/app/wwctl/node/list/main_test.go @@ -17,16 +17,14 @@ import ( func Test_List(t *testing.T) { tests := []struct { - name string - args []string - wantErr bool - stdout string - inDb string + name string + args []string + stdout string + inDb string }{ { - name: "single node list", - args: []string{}, - wantErr: false, + name: "single node list", + args: []string{}, stdout: `NODE NAME PROFILES NETWORK n01 default `, @@ -40,9 +38,8 @@ nodes: `, }, { - name: "multiple nodes list", - args: []string{}, - wantErr: false, + name: "multiple nodes list", + args: []string{}, stdout: `NODE NAME PROFILES NETWORK n01 default n02 default @@ -60,9 +57,8 @@ nodes: `, }, { - name: "node list returns multiple nodes", - args: []string{"n01,n02"}, - wantErr: false, + name: "node list returns multiple nodes", + args: []string{"n01,n02"}, stdout: `NODE NAME PROFILES NETWORK n01 default n02 default @@ -80,9 +76,8 @@ nodes: `, }, { - name: "node list returns multiple nodes (case 2)", - args: []string{"n01,n03"}, - wantErr: false, + name: "node list returns multiple nodes (case 2)", + args: []string{"n01,n03"}, stdout: `NODE NAME PROFILES NETWORK n01 default n03 default @@ -109,9 +104,8 @@ nodes: `, }, { - name: "node list returns one node", - args: []string{"n01,"}, - wantErr: false, + name: "node list returns one node", + args: []string{"n01,"}, stdout: `NODE NAME PROFILES NETWORK n01 default `, @@ -128,9 +122,8 @@ nodes: `, }, { - name: "node list profile with network", - args: []string{}, - wantErr: false, + name: "node list profile with network", + args: []string{}, stdout: `NODE NAME PROFILES NETWORK n01 default default `, @@ -146,9 +139,8 @@ nodes: - default `}, { - name: "node list profile with comment", - args: []string{"-a"}, - wantErr: false, + name: "node list profile with comment", + args: []string{"-a"}, stdout: `NODE FIELD PROFILE VALUE n01 Id -- n01 n01 Comment default profilecomment @@ -170,9 +162,8 @@ nodes: - default `}, { - name: "node list profile with comment superseded", - args: []string{"-a"}, - wantErr: false, + name: "node list profile with comment superseded", + args: []string{"-a"}, stdout: `NODE FIELD PROFILE VALUE n01 Id -- n01 n01 Comment SUPERSEDED nodecomment @@ -195,9 +186,8 @@ nodes: - default `}, { - name: "node list profile with ipmi user", - args: []string{"-i"}, - wantErr: false, + name: "node list profile with ipmi user", + args: []string{"-i"}, stdout: `NODE NAME IPMI IPADDR IPMI PORT IPMI USERNAME IPMI INTERFACE n01 -- -- admin -- -- `, @@ -212,9 +202,8 @@ nodes: - default `}, { - name: "node list profile with ipmi user superseded", - args: []string{"-i"}, - wantErr: false, + name: "node list profile with ipmi user superseded", + args: []string{"-i"}, stdout: `NODE NAME IPMI IPADDR IPMI PORT IPMI USERNAME IPMI INTERFACE n01 -- -- user -- -- `, @@ -241,9 +230,8 @@ nodes: - p1 - p2 `, - name: "multiple profiles list", - args: []string{}, - wantErr: false, + name: "multiple profiles list", + args: []string{}, stdout: `NODE NAME PROFILES NETWORK n01 p1,p2 `}, @@ -258,9 +246,8 @@ nodes: - p1 - p2 `, - name: "multiple profiles list all", - args: []string{"-a"}, - wantErr: false, + name: "multiple profiles list all", + args: []string{"-a"}, stdout: `NODE FIELD PROFILE VALUE n01 Id -- n01 n01 Ipxe -- (default) @@ -283,9 +270,8 @@ nodes: profiles: - p1 `, - name: "multiple overlays list", - args: []string{"-l"}, - wantErr: false, + name: "multiple overlays list", + args: []string{"-l"}, stdout: `NODE NAME KERNEL OVERRIDE CONTAINER OVERLAYS (S/R) n01 -- -- (wwinit)/rop1,rop2 `}, @@ -304,9 +290,8 @@ nodes: - nop1 - ~rop1 `, - name: "multiple overlays list", - args: []string{"-l"}, - wantErr: false, + name: "multiple overlays list", + args: []string{"-l"}, stdout: `NODE NAME KERNEL OVERRIDE CONTAINER OVERLAYS (S/R) n01 -- -- (wwinit)/rop2,nop1 ~{rop1} `}, @@ -325,9 +310,8 @@ nodes: - nop1 - ~rop1 `, - name: "multiple overlays list all", - args: []string{"-a"}, - wantErr: false, + name: "multiple overlays list all", + args: []string{"-a"}, stdout: `NODE FIELD PROFILE VALUE n01 Id -- n01 n01 Ipxe -- (default) @@ -351,9 +335,8 @@ nodes: system overlay: - nodeinit `, - name: "prefer profile system overlay over node overlay", - args: []string{"-a"}, - wantErr: false, + name: "prefer profile system overlay over node overlay", + args: []string{"-a"}, stdout: `NODE FIELD PROFILE VALUE n01 Id -- n01 n01 Ipxe -- (default) @@ -508,6 +491,9 @@ nodes: func verifyOutput(t *testing.T, baseCmd *cobra.Command, content string) { stdoutR, stdoutW, _ := os.Pipe() os.Stdout = stdoutW + wwlog.SetLogWriter(os.Stdout) + baseCmd.SetOut(os.Stdout) + baseCmd.SetErr(os.Stdout) err := baseCmd.Execute() assert.NoError(t, err) diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index 54839363..d939d5e7 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -32,11 +32,12 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err if vars.showYaml || vars.showJson { wwlog.Info(profileInfo.Output[0]) } else { - ph := helper.NewPrintHelper(strings.Split(profileInfo.Output[0], ":=:")) + ph := helper.New(strings.Split(profileInfo.Output[0], ":=:")) for _, val := range profileInfo.Output[1:] { ph.Append(strings.Split(val, ":=:")) } ph.Render() + wwlog.Info(ph.String()) } } return diff --git a/internal/app/wwctl/profile/list/main_test.go b/internal/app/wwctl/profile/list/main_test.go index 34b9a753..db8174e3 100644 --- a/internal/app/wwctl/profile/list/main_test.go +++ b/internal/app/wwctl/profile/list/main_test.go @@ -222,11 +222,12 @@ nodes: } func verifyOutput(t *testing.T, baseCmd *cobra.Command, content string) { - baseCmd.SetOut(nil) - baseCmd.SetErr(nil) stdoutR, stdoutW, _ := os.Pipe() oriout := os.Stdout os.Stdout = stdoutW + wwlog.SetLogWriter(os.Stdout) + baseCmd.SetOut(os.Stdout) + baseCmd.SetErr(os.Stdout) err := baseCmd.Execute() assert.NoError(t, err)