Merge pull request #1408 from JasonYangShadow/issue/1241

Fix excessive line spacing issue when listing nodes
This commit is contained in:
Jonathon Anderson
2024-09-25 13:52:29 -06:00
committed by GitHub
9 changed files with 78 additions and 72 deletions

View File

@@ -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

View File

@@ -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("%s", 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("%s", 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("%s", 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("%s", ph.String())
}
return
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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("")))
}

View File

@@ -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("%s", ph.String())
}
}
return

View File

@@ -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)

View File

@@ -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("%s", ph.String())
}
}
return

View File

@@ -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)