From f53ae48ae661e008ab2e7df345dcc28361b50dd8 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 5 Dec 2023 20:04:32 +0100 Subject: [PATCH] added test for power status Signed-off-by: Christian Goll --- internal/app/wwctl/power/cycle/main.go | 60 +++++++++---------- internal/app/wwctl/power/cycle/root.go | 31 +++++++--- internal/app/wwctl/power/cycle/root_test.go | 42 ++++++++++++++ internal/app/wwctl/power/off/main.go | 60 +++++++++---------- internal/app/wwctl/power/off/root.go | 16 +++-- internal/app/wwctl/power/off/root_test.go | 42 ++++++++++++++ internal/app/wwctl/power/on/main.go | 61 ++++++++++---------- internal/app/wwctl/power/on/root.go | 16 +++-- internal/app/wwctl/power/on/root_test.go | 42 ++++++++++++++ internal/app/wwctl/power/reset/main.go | 56 ++++++++++-------- internal/app/wwctl/power/reset/root.go | 16 +++-- internal/app/wwctl/power/reset/root_test.go | 42 ++++++++++++++ internal/app/wwctl/power/soft/main.go | 49 ++++++++-------- internal/app/wwctl/power/soft/root.go | 19 +++--- internal/app/wwctl/power/soft/root_test.go | 42 ++++++++++++++ internal/app/wwctl/power/status/root_test.go | 42 ++++++++++++++ internal/pkg/testenv/testenv.go | 20 ++++++- 17 files changed, 486 insertions(+), 170 deletions(-) create mode 100644 internal/app/wwctl/power/cycle/root_test.go create mode 100644 internal/app/wwctl/power/off/root_test.go create mode 100644 internal/app/wwctl/power/on/root_test.go create mode 100644 internal/app/wwctl/power/reset/root_test.go create mode 100644 internal/app/wwctl/power/soft/root_test.go create mode 100644 internal/app/wwctl/power/status/root_test.go diff --git a/internal/app/wwctl/power/cycle/main.go b/internal/app/wwctl/power/cycle/main.go index 38ac38e6..9ffd0aa6 100644 --- a/internal/app/wwctl/power/cycle/main.go +++ b/internal/app/wwctl/power/cycle/main.go @@ -12,8 +12,9 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - var returnErr error = nil +func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) { + return func(cmd *cobra.Command, args []string) error { + var returnErr error = nil nodeDB, err := node.New() if err != nil { @@ -25,23 +26,23 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("could not get node list: %s", err) } - if len(args) > 0 { - nodes = node.FilterNodeListByName(nodes, hostlist.Expand(args)) - } else { - //nolint:errcheck - cmd.Usage() - os.Exit(1) - } + if len(args) > 0 { + nodes = node.FilterByName(nodes, hostlist.Expand(args)) + } else { + //nolint:errcheck + cmd.Usage() + os.Exit(1) + } if len(nodes) == 0 { return fmt.Errorf("no nodes found") } - batchpool := batch.New(50) - jobcount := len(nodes) - results := make(chan power.IPMI, jobcount) + batchpool := batch.New(50) + jobcount := len(nodes) + results := make(chan power.IPMI, jobcount) - for _, n := range nodes { + for _, n := range nodes { if node.Ipmi.Ipaddr.IsUnspecified() { wwlog.Error("%s: No IPMI IP address", node.Id()) @@ -56,25 +57,24 @@ func CobraRunE(cmd *cobra.Command, args []string) error { results <- ipmiCmd }) - } - - batchpool.Run() - - close(results) - - for result := range results { - - out, err := result.Result() - - if err != nil { - wwlog.Error("%s: %s", result.Ipaddr, out) - returnErr = err - continue } - fmt.Printf("%s: %s\n", result.Ipaddr, out) + batchpool.Run() + close(results) + + for result := range results { + + out, err := result.Result() + + if err != nil { + wwlog.Error("%s: %s", result.Ipaddr, out) + returnErr = err + continue + } + wwlog.Info("%s: %s\n", result.Ipaddr, out) + } + + return returnErr } - - return returnErr } diff --git a/internal/app/wwctl/power/cycle/root.go b/internal/app/wwctl/power/cycle/root.go index 803ba0da..9054a5ea 100644 --- a/internal/app/wwctl/power/cycle/root.go +++ b/internal/app/wwctl/power/cycle/root.go @@ -2,19 +2,36 @@ package cycle import ( "github.com/spf13/cobra" + "github.com/warewulf/warewulf/internal/pkg/node" ) -var ( - powerCmd = &cobra.Command{ +type variables struct { + Showcmd bool +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + vars := variables{} + powerCmd := &cobra.Command{ DisableFlagsInUseLine: true, Use: "cycle [OPTIONS] [PATTERN ...]", Short: "Power cycle the given node(s)", Long: "This command cycles power for a set of nodes specified by PATTERN.", - RunE: CobraRunE, - } -) + RunE: CobraRunE(&vars), + ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) != 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { + nodeDB, _ := node.New() + nodes, _ := nodeDB.FindAllNodes() + var node_names []string + for _, node := range nodes { + node_names = append(node_names, node.Id.Get()) + } + return node_names, cobra.ShellCompDirectiveNoFileComp + }, + } + powerCmd.PersistentFlags().BoolVarP(&vars.Showcmd, "show", "s", false, "only show command which will be executed") return powerCmd } diff --git a/internal/app/wwctl/power/cycle/root_test.go b/internal/app/wwctl/power/cycle/root_test.go new file mode 100644 index 00000000..37f4dca1 --- /dev/null +++ b/internal/app/wwctl/power/cycle/root_test.go @@ -0,0 +1,42 @@ +package powercycle + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" +) + +func Test_Power_Status(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll(t) + + env.WriteFile(t, "etc/warewulf/nodes.conf", `WW_INTERNAL: 43 +nodeprofiles: + default: + ipmi: + username: admin + password: admin +nodes: + n01: + profiles: + - default + ipmi: + ipaddr: 10.10.10.10`) + warewulfd.SetNoDaemon() + t.Run("ipmitool status test", func(t *testing.T) { + baseCmd := GetCommand() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + wwlog.SetLogWriter(buf) + baseCmd.SetArgs([]string{"--show", "n01"}) + err := baseCmd.Execute() + assert.NoError(t, err) + assert.Equal(t, "10.10.10.10: ipmitool -I lan -H 10.10.10.10 -p 623 -U admin -P admin -e ~ chassis power cycle", strings.TrimSpace(buf.String())) + }) +} diff --git a/internal/app/wwctl/power/off/main.go b/internal/app/wwctl/power/off/main.go index 939d9a66..60f156e8 100644 --- a/internal/app/wwctl/power/off/main.go +++ b/internal/app/wwctl/power/off/main.go @@ -12,8 +12,9 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - var returnErr error = nil +func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) { + return func(cmd *cobra.Command, args []string) error { + var returnErr error = nil nodeDB, err := node.New() if err != nil { @@ -25,21 +26,21 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("could not get node list: %s", err) } - if len(args) > 0 { - nodes = node.FilterNodeListByName(nodes, hostlist.Expand(args)) - } else { - //nolint:errcheck - cmd.Usage() - os.Exit(1) - } + if len(args) > 0 { + nodes = node.FilterByName(nodes, hostlist.Expand(args)) + } else { + //nolint:errcheck + cmd.Usage() + os.Exit(1) + } if len(nodes) == 0 { return fmt.Errorf("no nodes found") } - batchpool := batch.New(50) - jobcount := len(nodes) - results := make(chan power.IPMI, jobcount) + batchpool := batch.New(50) + jobcount := len(nodes) + results := make(chan power.IPMI, jobcount) for _, node := range nodes { @@ -56,25 +57,26 @@ func CobraRunE(cmd *cobra.Command, args []string) error { results <- ipmiCmd }) - } - - batchpool.Run() - - close(results) - - for result := range results { - - out, err := result.Result() - - if err != nil { - wwlog.Error("%s: %s", result.Ipaddr, out) - returnErr = err - continue } - fmt.Printf("%s: %s\n", result.Ipaddr, out) + batchpool.Run() + close(results) + + for result := range results { + + out, err := result.Result() + + if err != nil { + wwlog.Error("%s: %s", result.Ipaddr, out) + returnErr = err + continue + } + + wwlog.Info("%s: %s\n", result.Ipaddr, out) + + } + + return returnErr } - - return returnErr } diff --git a/internal/app/wwctl/power/off/root.go b/internal/app/wwctl/power/off/root.go index 004ad427..bedd5c9e 100644 --- a/internal/app/wwctl/power/off/root.go +++ b/internal/app/wwctl/power/off/root.go @@ -5,13 +5,19 @@ import ( "github.com/warewulf/warewulf/internal/pkg/node" ) -var ( - powerCmd = &cobra.Command{ +type variables struct { + Showcmd bool +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + vars := variables{} + powerCmd := &cobra.Command{ DisableFlagsInUseLine: true, Use: "off [OPTIONS] [PATTERN ...]", Short: "Power off the given node(s)", Long: "This command will shutdown power to a set of nodes specified by PATTERN.", - RunE: CobraRunE, + RunE: CobraRunE(&vars), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp @@ -26,9 +32,7 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } -) + powerCmd.PersistentFlags().BoolVarP(&vars.Showcmd, "show", "s", false, "only show command which will be executed") -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { return powerCmd } diff --git a/internal/app/wwctl/power/off/root_test.go b/internal/app/wwctl/power/off/root_test.go new file mode 100644 index 00000000..7af6e297 --- /dev/null +++ b/internal/app/wwctl/power/off/root_test.go @@ -0,0 +1,42 @@ +package poweroff + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" +) + +func Test_Power_Status(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll(t) + + env.WriteFile(t, "etc/warewulf/nodes.conf", `WW_INTERNAL: 43 +nodeprofiles: + default: + ipmi: + username: admin + password: admin +nodes: + n01: + profiles: + - default + ipmi: + ipaddr: 10.10.10.10`) + warewulfd.SetNoDaemon() + t.Run("ipmitool status test", func(t *testing.T) { + baseCmd := GetCommand() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + wwlog.SetLogWriter(buf) + baseCmd.SetArgs([]string{"--show", "n01"}) + err := baseCmd.Execute() + assert.NoError(t, err) + assert.Equal(t, "10.10.10.10: ipmitool -I lan -H 10.10.10.10 -p 623 -U admin -P admin -e ~ chassis power off", strings.TrimSpace(buf.String())) + }) +} diff --git a/internal/app/wwctl/power/on/main.go b/internal/app/wwctl/power/on/main.go index 4e517ea7..b19ba533 100644 --- a/internal/app/wwctl/power/on/main.go +++ b/internal/app/wwctl/power/on/main.go @@ -12,8 +12,10 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - var returnErr error = nil +func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) { + return func(cmd *cobra.Command, args []string) error { + + var returnErr error = nil nodeDB, err := node.New() if err != nil { @@ -25,21 +27,21 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("could not get node list: %s", err) } - if len(args) > 0 { - nodes = node.FilterNodeListByName(nodes, hostlist.Expand(args)) - } else { - //nolint:errcheck - cmd.Usage() - os.Exit(1) - } + if len(args) > 0 { + nodes = node.FilterByName(nodes, hostlist.Expand(args)) + } else { + //nolint:errcheck + cmd.Usage() + os.Exit(1) + } if len(nodes) == 0 { return fmt.Errorf("no nodes found") } - batchpool := batch.New(50) - jobcount := len(nodes) - results := make(chan power.IPMI, jobcount) + batchpool := batch.New(50) + jobcount := len(nodes) + results := make(chan power.IPMI, jobcount) for _, node := range nodes { @@ -56,25 +58,26 @@ func CobraRunE(cmd *cobra.Command, args []string) error { results <- ipmiCmd }) - } - - batchpool.Run() - - close(results) - - for result := range results { - - out, err := result.Result() - - if err != nil { - wwlog.Error("%s: %s", result.Ipaddr, out) - returnErr = err - continue } - fmt.Printf("%s: %s\n", result.Ipaddr, out) + batchpool.Run() + close(results) + + for result := range results { + + out, err := result.Result() + + if err != nil { + wwlog.Error("%s: %s", result.Ipaddr, out) + returnErr = err + continue + } + + wwlog.Info("%s: %s\n", result.Ipaddr, out) + + } + + return returnErr } - - return returnErr } diff --git a/internal/app/wwctl/power/on/root.go b/internal/app/wwctl/power/on/root.go index 42c0ebf4..8fb83ff2 100644 --- a/internal/app/wwctl/power/on/root.go +++ b/internal/app/wwctl/power/on/root.go @@ -5,12 +5,18 @@ import ( "github.com/warewulf/warewulf/internal/pkg/node" ) -var ( - powerCmd = &cobra.Command{ +type variables struct { + Showcmd bool +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + vars := variables{} + powerCmd := &cobra.Command{ Use: "on [OPTIONS] [PATTERN ...]", Short: "Power on the given node(s)", Long: "This command will power on a set of nodes specified by PATTERN.", - RunE: CobraRunE, + RunE: CobraRunE(&vars), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp @@ -25,9 +31,7 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } -) + powerCmd.PersistentFlags().BoolVarP(&vars.Showcmd, "show", "s", false, "only show command which will be executed") -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { return powerCmd } diff --git a/internal/app/wwctl/power/on/root_test.go b/internal/app/wwctl/power/on/root_test.go new file mode 100644 index 00000000..0dd39ba8 --- /dev/null +++ b/internal/app/wwctl/power/on/root_test.go @@ -0,0 +1,42 @@ +package poweron + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" +) + +func Test_Power_Status(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll(t) + + env.WriteFile(t, "etc/warewulf/nodes.conf", `WW_INTERNAL: 43 +nodeprofiles: + default: + ipmi: + username: admin + password: admin +nodes: + n01: + profiles: + - default + ipmi: + ipaddr: 10.10.10.10`) + warewulfd.SetNoDaemon() + t.Run("ipmitool status test", func(t *testing.T) { + baseCmd := GetCommand() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + wwlog.SetLogWriter(buf) + baseCmd.SetArgs([]string{"--show", "n01"}) + err := baseCmd.Execute() + assert.NoError(t, err) + assert.Equal(t, "10.10.10.10: ipmitool -I lan -H 10.10.10.10 -p 623 -U admin -P admin -e ~ chassis power on", strings.TrimSpace(buf.String())) + }) +} diff --git a/internal/app/wwctl/power/reset/main.go b/internal/app/wwctl/power/reset/main.go index 89b0e5bb..1abe3d3c 100644 --- a/internal/app/wwctl/power/reset/main.go +++ b/internal/app/wwctl/power/reset/main.go @@ -12,8 +12,10 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - var returnErr error = nil +func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) { + return func(cmd *cobra.Command, args []string) error { + + var returnErr error = nil nodeDB, err := node.New() if err != nil { @@ -25,6 +27,13 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("cloud not get nodeList: %s", err) } + if len(args) > 0 { + nodes = node.FilterByName(nodes, hostlist.Expand(args)) + } else { + //nolint:errcheck + cmd.Usage() + os.Exit(1) + } if len(args) > 0 { nodes = node.FilterNodeListByName(nodes, hostlist.Expand(args)) } else { @@ -37,11 +46,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("no nodes found") } - batchpool := batch.New(50) - jobcount := len(nodes) - results := make(chan power.IPMI, jobcount) + batchpool := batch.New(50) + jobcount := len(nodes) + results := make(chan power.IPMI, jobcount) - for _, n := range nodes { + for _, n := range nodes { if node.Ipmi.Ipaddr.IsUnspecified() { wwlog.Error("%s: No IPMI IP address", node.Id()) @@ -56,25 +65,26 @@ func CobraRunE(cmd *cobra.Command, args []string) error { results <- ipmiCmd }) - } - - batchpool.Run() - - close(results) - - for result := range results { - - out, err := result.Result() - - if err != nil { - wwlog.Error("%s: %s", result.Ipaddr, out) - returnErr = err - continue } - fmt.Printf("%s: %s\n", result.Ipaddr, out) + batchpool.Run() + close(results) + + for result := range results { + + out, err := result.Result() + + if err != nil { + wwlog.Error("%s: %s", result.Ipaddr, out) + returnErr = err + continue + } + + wwlog.Info("%s: %s\n", result.Ipaddr, out) + + } + + return returnErr } - - return returnErr } diff --git a/internal/app/wwctl/power/reset/root.go b/internal/app/wwctl/power/reset/root.go index 7be3abdf..bdab6b84 100644 --- a/internal/app/wwctl/power/reset/root.go +++ b/internal/app/wwctl/power/reset/root.go @@ -5,13 +5,19 @@ import ( "github.com/warewulf/warewulf/internal/pkg/node" ) -var ( - powerCmd = &cobra.Command{ +type variables struct { + Showcmd bool +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + vars := variables{} + powerCmd := &cobra.Command{ DisableFlagsInUseLine: true, Use: "reset [OPTIONS] [PATTERN ...]", Short: "Issue a reset to node(s)", Long: "This command will issue a reset to a set of nodes specified by PATTERN.", - RunE: CobraRunE, + RunE: CobraRunE(&vars), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp @@ -26,9 +32,7 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } -) + powerCmd.PersistentFlags().BoolVarP(&vars.Showcmd, "show", "s", false, "only show command which will be executed") -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { return powerCmd } diff --git a/internal/app/wwctl/power/reset/root_test.go b/internal/app/wwctl/power/reset/root_test.go new file mode 100644 index 00000000..d486d2d4 --- /dev/null +++ b/internal/app/wwctl/power/reset/root_test.go @@ -0,0 +1,42 @@ +package powerreset + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" +) + +func Test_Power_Status(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll(t) + + env.WriteFile(t, "etc/warewulf/nodes.conf", `WW_INTERNAL: 43 +nodeprofiles: + default: + ipmi: + username: admin + password: admin +nodes: + n01: + profiles: + - default + ipmi: + ipaddr: 10.10.10.10`) + warewulfd.SetNoDaemon() + t.Run("ipmitool status test", func(t *testing.T) { + baseCmd := GetCommand() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + wwlog.SetLogWriter(buf) + baseCmd.SetArgs([]string{"--show", "n01"}) + err := baseCmd.Execute() + assert.NoError(t, err) + assert.Equal(t, "10.10.10.10: ipmitool -I lan -H 10.10.10.10 -p 623 -U admin -P admin -e ~ chassis power reset", strings.TrimSpace(buf.String())) + }) +} diff --git a/internal/app/wwctl/power/soft/main.go b/internal/app/wwctl/power/soft/main.go index 955a9b63..5027707b 100644 --- a/internal/app/wwctl/power/soft/main.go +++ b/internal/app/wwctl/power/soft/main.go @@ -12,8 +12,10 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - var returnErr error = nil +func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) { + return func(cmd *cobra.Command, args []string) error { + + var returnErr error = nil nodeDB, err := node.New() if err != nil { @@ -37,11 +39,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("no nodes found") } - batchpool := batch.New(50) - jobcount := len(nodes) - results := make(chan power.IPMI, jobcount) + batchpool := batch.New(50) + jobcount := len(nodes) + results := make(chan power.IPMI, jobcount) - for _, n := range nodes { + for _, n := range nodes { if node.Ipmi.Ipaddr.IsUnspecified() { wwlog.Error("%s: No IPMI IP address", node.Id()) @@ -56,25 +58,26 @@ func CobraRunE(cmd *cobra.Command, args []string) error { results <- ipmiCmd }) - } - - batchpool.Run() - - close(results) - - for result := range results { - - out, err := result.Result() - - if err != nil { - wwlog.Error("%s: %s", result.Ipaddr, out) - returnErr = err - continue } - fmt.Printf("%s: %s\n", result.Ipaddr, out) + batchpool.Run() + close(results) + + for result := range results { + + out, err := result.Result() + + if err != nil { + wwlog.Error("%s: %s", result.Ipaddr, out) + returnErr = err + continue + } + + wwlog.Info("%s: %s\n", result.Ipaddr, out) + + } + + return returnErr } - - return returnErr } diff --git a/internal/app/wwctl/power/soft/root.go b/internal/app/wwctl/power/soft/root.go index 791aa0e0..6c7df0c3 100644 --- a/internal/app/wwctl/power/soft/root.go +++ b/internal/app/wwctl/power/soft/root.go @@ -5,13 +5,19 @@ import ( "github.com/warewulf/warewulf/internal/pkg/node" ) -var ( - powerCmd = &cobra.Command{ +type variables struct { + Showcmd bool +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + vars := variables{} + powerCmd := &cobra.Command{ DisableFlagsInUseLine: true, Use: "soft", Short: "Gracefully shuts down the given node(s)", - Long: "This command uses the operating system to shut down the set of nodes specified by PATTERN.", - RunE: CobraRunE, + Long: "This command uses the operationg system to shut down the set of nodes specified by PATTERN.", + RunE: CobraRunE(&vars), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp @@ -26,9 +32,6 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } -) - -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { + powerCmd.PersistentFlags().BoolVarP(&vars.Showcmd, "show", "s", false, "only show command which will be executed") return powerCmd } diff --git a/internal/app/wwctl/power/soft/root_test.go b/internal/app/wwctl/power/soft/root_test.go new file mode 100644 index 00000000..87bb00b3 --- /dev/null +++ b/internal/app/wwctl/power/soft/root_test.go @@ -0,0 +1,42 @@ +package powersoft + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" +) + +func Test_Power_Status(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll(t) + + env.WriteFile(t, "etc/warewulf/nodes.conf", `WW_INTERNAL: 43 +nodeprofiles: + default: + ipmi: + username: admin + password: admin +nodes: + n01: + profiles: + - default + ipmi: + ipaddr: 10.10.10.10`) + warewulfd.SetNoDaemon() + t.Run("ipmitool status test", func(t *testing.T) { + baseCmd := GetCommand() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + wwlog.SetLogWriter(buf) + baseCmd.SetArgs([]string{"--show", "n01"}) + err := baseCmd.Execute() + assert.NoError(t, err) + assert.Equal(t, "10.10.10.10: ipmitool -I lan -H 10.10.10.10 -p 623 -U admin -P admin -e ~ chassis power soft", strings.TrimSpace(buf.String())) + }) +} diff --git a/internal/app/wwctl/power/status/root_test.go b/internal/app/wwctl/power/status/root_test.go new file mode 100644 index 00000000..4446c37c --- /dev/null +++ b/internal/app/wwctl/power/status/root_test.go @@ -0,0 +1,42 @@ +package powerstatus + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/warewulfd" + "github.com/warewulf/warewulf/internal/pkg/wwlog" +) + +func Test_Power_Status(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll(t) + + env.WriteFile(t, "etc/warewulf/nodes.conf", `WW_INTERNAL: 43 +nodeprofiles: + default: + ipmi: + username: admin + password: admin +nodes: + n01: + profiles: + - default + ipmi: + ipaddr: 10.10.10.10`) + warewulfd.SetNoDaemon() + t.Run("ipmitool status test", func(t *testing.T) { + baseCmd := GetCommand() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + wwlog.SetLogWriter(buf) + baseCmd.SetArgs([]string{"--show", "n01"}) + err := baseCmd.Execute() + assert.NoError(t, err) + assert.Equal(t, "10.10.10.10: ipmitool -I lan -H 10.10.10.10 -p 623 -U admin -P admin -e ~ chassis power status", strings.TrimSpace(buf.String())) + }) +} diff --git a/internal/pkg/testenv/testenv.go b/internal/pkg/testenv/testenv.go index 94d88a83..1afc6c63 100644 --- a/internal/pkg/testenv/testenv.go +++ b/internal/pkg/testenv/testenv.go @@ -9,6 +9,7 @@ import ( "os" "path" "path/filepath" + "runtime" "testing" "time" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/warewulf/warewulf/internal/pkg/node" + "github.com/warewulf/warewulf/internal/pkg/util" ) const initWarewulfConf = `WW_INTERNAL: 0` @@ -93,9 +95,15 @@ func New(t *testing.T) (env *TestEnv) { conf.Paths.WWChrootdir, conf.Paths.WWProvisiondir, } { - env.MkdirAll(t, confPath) + env.MkdirAllAbs(t, confPath) } - + // copy templates + _, b, _, _ := runtime.Caller(0) + basepath := filepath.Dir(b) + env.MkdirAllAbs(t, path.Join(conf.Warewulf.DataStore, "warewulf/bmc")) + assert.DirExists(t, path.Join(conf.Warewulf.DataStore, "warewulf/bmc")) + err = util.CopyFile(path.Join(basepath, "../../../lib/warewulf/bmc/ipmitool.tmpl"), path.Join(conf.Warewulf.DataStore, "warewulf/bmc/ipmitool.tmpl")) + assert.NoError(t, err) // node.init() has already run, so set the config path again node.ConfigFile = env.GetPath(path.Join(Sysconfdir, "warewulf/nodes.conf")) @@ -110,13 +118,19 @@ func (env *TestEnv) GetPath(fileName string) string { // MkdirAll creates dirName and any intermediate directories relative // to the test environment. -// // Asserts no errors occur. func (env *TestEnv) MkdirAll(t *testing.T, dirName string) { err := os.MkdirAll(env.GetPath(dirName), 0755) assert.NoError(t, err) } +// MkdirAllAbs creates absolute dirName and any intermediate directories +// Asserts no errors occur. +func (env *TestEnv) MkdirAllAbs(t *testing.T, dirName string) { + err := os.MkdirAll(dirName, 0755) + assert.NoError(t, err) +} + // WriteFile writes content to fileName, creating any necessary // intermediate directories relative to the test environment. //