Don't allow to run baremetal actions without flags

With this change we will be sure that no commands against bmh
hosts will be applied without selector flags specified, now if you
want to target all hosts in inventory you must specify --all flag

Relates-To: #364
Related-To: #364

Closes: #364
Change-Id: I0d615ea226528162e07acc96fa61b26e031145aa
This commit is contained in:
Kostiantyn Kalynovskyi 2021-02-09 22:52:17 +00:00 committed by Kostyantyn Kalynovskyi
parent abc8315828
commit 7dfb0eb98c
19 changed files with 395 additions and 34 deletions

View File

@ -15,6 +15,7 @@
package baremetal package baremetal
import ( import (
"fmt"
"time" "time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -40,6 +41,29 @@ const (
flagTimeout = "timeout" flagTimeout = "timeout"
flagTimeoutDescription = "timeout on baremetal action" flagTimeoutDescription = "timeout on baremetal action"
flagAll = "all"
flagAllDescription = "specify this to target all hosts in the inventory"
)
var (
selectorsDescription = fmt.Sprintf(`The command will target baremetal hosts from airship inventory kustomize root
based on the --%s, --%s and --%s flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory`, flagName, flagNamespace, flagLabel)
bmhActionExampleTempalte = `
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal %[1]s --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal %[1]s --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal %[1]s --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal %[1]s --labels "foo=bar"
`
) )
// NewBaremetalCommand creates a new command for interacting with baremetal using airshipctl. // NewBaremetalCommand creates a new command for interacting with baremetal using airshipctl.
@ -67,3 +91,7 @@ func initFlags(options *inventory.CommandOptions, cmd *cobra.Command) {
flags.StringVarP(&options.Namespace, flagNamespace, flagNamespaceSort, "", flagNamespaceDescription) flags.StringVarP(&options.Namespace, flagNamespace, flagNamespaceSort, "", flagNamespaceDescription)
flags.DurationVar(&options.Timeout, flagTimeout, 10*time.Minute, flagTimeoutDescription) flags.DurationVar(&options.Timeout, flagTimeout, 10*time.Minute, flagTimeoutDescription)
} }
func initAllFlag(options *inventory.CommandOptions, cmd *cobra.Command) {
cmd.Flags().BoolVar(&options.All, flagAll, false, flagAllDescription)
}

View File

@ -15,6 +15,8 @@
package baremetal package baremetal
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
@ -22,11 +24,24 @@ import (
"opendev.org/airship/airshipctl/pkg/inventory/ifc" "opendev.org/airship/airshipctl/pkg/inventory/ifc"
) )
var (
ejectMediaCommand = "ejectmedia"
ejectMediaLong = fmt.Sprintf(`
Eject media attached to a baremetal hosts
%s
`, selectorsDescription)
ejectMediaExample = fmt.Sprintf(bmhActionExampleTempalte, ejectMediaCommand)
)
// NewEjectMediaCommand provides a command to eject media attached to a baremetal host. // NewEjectMediaCommand provides a command to eject media attached to a baremetal host.
func NewEjectMediaCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command { func NewEjectMediaCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "ejectmedia", Use: ejectMediaCommand,
Short: "Eject media attached to a baremetal host", Short: "Eject media attached to a baremetal hosts",
Long: ejectMediaLong[1:],
Example: ejectMediaExample[1:],
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return options.BMHAction(ifc.BaremetalOperationEjectVirtualMedia) return options.BMHAction(ifc.BaremetalOperationEjectVirtualMedia)
@ -34,6 +49,7 @@ func NewEjectMediaCommand(cfgFactory config.Factory, options *inventory.CommandO
} }
initFlags(options, cmd) initFlags(options, cmd)
initAllFlag(options, cmd)
return cmd return cmd
} }

View File

@ -15,6 +15,8 @@
package baremetal package baremetal
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
@ -22,11 +24,24 @@ import (
"opendev.org/airship/airshipctl/pkg/inventory/ifc" "opendev.org/airship/airshipctl/pkg/inventory/ifc"
) )
var (
powerOffCommand = "poweroff"
powerOffLong = fmt.Sprintf(`
Power off baremetal hosts
%s
`, selectorsDescription)
powerOffExample = fmt.Sprintf(bmhActionExampleTempalte, powerOffCommand)
)
// NewPowerOffCommand provides a command to shutdown a remote host. // NewPowerOffCommand provides a command to shutdown a remote host.
func NewPowerOffCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command { func NewPowerOffCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "poweroff", Use: powerOffCommand,
Short: "Shutdown a baremetal host", Short: "Shutdown a baremetal hosts",
Long: powerOffLong[1:],
Example: powerOffExample[1:],
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return options.BMHAction(ifc.BaremetalOperationPowerOff) return options.BMHAction(ifc.BaremetalOperationPowerOff)
@ -34,6 +49,7 @@ func NewPowerOffCommand(cfgFactory config.Factory, options *inventory.CommandOpt
} }
initFlags(options, cmd) initFlags(options, cmd)
initAllFlag(options, cmd)
return cmd return cmd
} }

View File

@ -15,6 +15,8 @@ Licensed under the Apache License, Version 2.0 (the "License");
package baremetal package baremetal
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
@ -22,11 +24,24 @@ import (
"opendev.org/airship/airshipctl/pkg/inventory/ifc" "opendev.org/airship/airshipctl/pkg/inventory/ifc"
) )
var (
powerOnCommand = "poweron"
powerOnLong = fmt.Sprintf(`
Power on baremetal hosts
%s
`, selectorsDescription)
powerOnExample = fmt.Sprintf(bmhActionExampleTempalte, powerOnCommand)
)
// NewPowerOnCommand provides a command with the capability to power on baremetal hosts. // NewPowerOnCommand provides a command with the capability to power on baremetal hosts.
func NewPowerOnCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command { func NewPowerOnCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "poweron", Use: powerOnCommand,
Short: "Power on a host", Short: "Power on a hosts",
Long: powerOnLong[1:],
Example: powerOnExample[1:],
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return options.BMHAction(ifc.BaremetalOperationPowerOn) return options.BMHAction(ifc.BaremetalOperationPowerOn)
@ -34,6 +49,7 @@ func NewPowerOnCommand(cfgFactory config.Factory, options *inventory.CommandOpti
} }
initFlags(options, cmd) initFlags(options, cmd)
initAllFlag(options, cmd)
return cmd return cmd
} }

View File

@ -15,6 +15,8 @@ Licensed under the Apache License, Version 2.0 (the "License");
package baremetal package baremetal
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
@ -22,11 +24,24 @@ import (
"opendev.org/airship/airshipctl/pkg/inventory/ifc" "opendev.org/airship/airshipctl/pkg/inventory/ifc"
) )
var (
rebootCommand = "reboot"
rebootLong = fmt.Sprintf(`
Reboot baremetal hosts
%s
`, selectorsDescription)
rebootExample = fmt.Sprintf(bmhActionExampleTempalte, rebootCommand)
)
// NewRebootCommand provides a command with the capability to reboot baremetal hosts. // NewRebootCommand provides a command with the capability to reboot baremetal hosts.
func NewRebootCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command { func NewRebootCommand(cfgFactory config.Factory, options *inventory.CommandOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "reboot", Use: rebootCommand,
Short: "Reboot a host", Long: rebootLong[1:],
Short: "Reboot a hosts",
Example: rebootExample[1:],
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return options.BMHAction(ifc.BaremetalOperationReboot) return options.BMHAction(ifc.BaremetalOperationReboot)
@ -34,6 +49,7 @@ func NewRebootCommand(cfgFactory config.Factory, options *inventory.CommandOptio
} }
initFlags(options, cmd) initFlags(options, cmd)
initAllFlag(options, cmd)
return cmd return cmd
} }

View File

@ -1,9 +1,27 @@
Eject media attached to a baremetal host Eject media attached to a baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
Usage: Usage:
ejectmedia [flags] ejectmedia [flags]
Examples:
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal ejectmedia --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal ejectmedia --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal ejectmedia --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal ejectmedia --labels "foo=bar"
Flags: Flags:
--all specify this to target all hosts in the inventory
-h, --help help for ejectmedia -h, --help help for ejectmedia
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -1,9 +1,27 @@
Shutdown a baremetal host Power off baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
Usage: Usage:
poweroff [flags] poweroff [flags]
Examples:
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal poweroff --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal poweroff --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal poweroff --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal poweroff --labels "foo=bar"
Flags: Flags:
--all specify this to target all hosts in the inventory
-h, --help help for poweroff -h, --help help for poweroff
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -1,9 +1,27 @@
Power on a host Power on baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
Usage: Usage:
poweron [flags] poweron [flags]
Examples:
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal poweron --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal poweron --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal poweron --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal poweron --labels "foo=bar"
Flags: Flags:
--all specify this to target all hosts in the inventory
-h, --help help for poweron -h, --help help for poweron
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -1,9 +1,27 @@
Reboot a host Reboot baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
Usage: Usage:
reboot [flags] reboot [flags]
Examples:
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal reboot --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal reboot --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal reboot --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal reboot --labels "foo=bar"
Flags: Flags:
--all specify this to target all hosts in the inventory
-h, --help help for reboot -h, --help help for reboot
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -4,12 +4,12 @@ Usage:
baremetal [command] baremetal [command]
Available Commands: Available Commands:
ejectmedia Eject media attached to a baremetal host ejectmedia Eject media attached to a baremetal hosts
help Help about any command help Help about any command
poweroff Shutdown a baremetal host poweroff Shutdown a baremetal hosts
poweron Power on a host poweron Power on a hosts
powerstatus Retrieve the power status of a baremetal host powerstatus Retrieve the power status of a baremetal host
reboot Reboot a host reboot Reboot a hosts
remotedirect Bootstrap the ephemeral host remotedirect Bootstrap the ephemeral host
Flags: Flags:

View File

@ -22,10 +22,10 @@ Perform actions on baremetal hosts
### SEE ALSO ### SEE ALSO
* [airshipctl](airshipctl.md) - A unified entrypoint to various airship components * [airshipctl](airshipctl.md) - A unified entrypoint to various airship components
* [airshipctl baremetal ejectmedia](airshipctl_baremetal_ejectmedia.md) - Eject media attached to a baremetal host * [airshipctl baremetal ejectmedia](airshipctl_baremetal_ejectmedia.md) - Eject media attached to a baremetal hosts
* [airshipctl baremetal poweroff](airshipctl_baremetal_poweroff.md) - Shutdown a baremetal host * [airshipctl baremetal poweroff](airshipctl_baremetal_poweroff.md) - Shutdown a baremetal hosts
* [airshipctl baremetal poweron](airshipctl_baremetal_poweron.md) - Power on a host * [airshipctl baremetal poweron](airshipctl_baremetal_poweron.md) - Power on a hosts
* [airshipctl baremetal powerstatus](airshipctl_baremetal_powerstatus.md) - Retrieve the power status of a baremetal host * [airshipctl baremetal powerstatus](airshipctl_baremetal_powerstatus.md) - Retrieve the power status of a baremetal host
* [airshipctl baremetal reboot](airshipctl_baremetal_reboot.md) - Reboot a host * [airshipctl baremetal reboot](airshipctl_baremetal_reboot.md) - Reboot a hosts
* [airshipctl baremetal remotedirect](airshipctl_baremetal_remotedirect.md) - Bootstrap the ephemeral host * [airshipctl baremetal remotedirect](airshipctl_baremetal_remotedirect.md) - Bootstrap the ephemeral host

View File

@ -1,18 +1,40 @@
## airshipctl baremetal ejectmedia ## airshipctl baremetal ejectmedia
Eject media attached to a baremetal host Eject media attached to a baremetal hosts
### Synopsis ### Synopsis
Eject media attached to a baremetal host Eject media attached to a baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
``` ```
airshipctl baremetal ejectmedia [flags] airshipctl baremetal ejectmedia [flags]
``` ```
### Examples
```
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal ejectmedia --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal ejectmedia --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal ejectmedia --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal ejectmedia --labels "foo=bar"
```
### Options ### Options
``` ```
--all specify this to target all hosts in the inventory
-h, --help help for ejectmedia -h, --help help for ejectmedia
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -1,18 +1,40 @@
## airshipctl baremetal poweroff ## airshipctl baremetal poweroff
Shutdown a baremetal host Shutdown a baremetal hosts
### Synopsis ### Synopsis
Shutdown a baremetal host Power off baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
``` ```
airshipctl baremetal poweroff [flags] airshipctl baremetal poweroff [flags]
``` ```
### Examples
```
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal poweroff --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal poweroff --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal poweroff --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal poweroff --labels "foo=bar"
```
### Options ### Options
``` ```
--all specify this to target all hosts in the inventory
-h, --help help for poweroff -h, --help help for poweroff
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -1,18 +1,40 @@
## airshipctl baremetal poweron ## airshipctl baremetal poweron
Power on a host Power on a hosts
### Synopsis ### Synopsis
Power on a host Power on baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
``` ```
airshipctl baremetal poweron [flags] airshipctl baremetal poweron [flags]
``` ```
### Examples
```
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal poweron --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal poweron --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal poweron --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal poweron --labels "foo=bar"
```
### Options ### Options
``` ```
--all specify this to target all hosts in the inventory
-h, --help help for poweron -h, --help help for poweron
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -1,18 +1,40 @@
## airshipctl baremetal reboot ## airshipctl baremetal reboot
Reboot a host Reboot a hosts
### Synopsis ### Synopsis
Reboot a host Reboot baremetal hosts
The command will target baremetal hosts from airship inventory kustomize root
based on the --name, --namespace and --labels flags provided. If no flags are
provided airshipctl will try to select all baremetal hosts in the inventory
``` ```
airshipctl baremetal reboot [flags] airshipctl baremetal reboot [flags]
``` ```
### Examples
```
Perform action against hosts with name rdm9r3s3 in all namespaces where the host is found
# airshipctl baremetal reboot --name rdm9r3s3
Perform action against hosts with name rdm9r3s3 in namespace metal3
# airshipctl baremetal reboot --name rdm9r3s3 --namespace metal3
Perform action against all hosts defined in inventory
# airshipctl baremetal reboot --all
Perform action against hosts with a label 'foo=bar'
# airshipctl baremetal reboot --labels "foo=bar"
```
### Options ### Options
``` ```
--all specify this to target all hosts in the inventory
-h, --help help for reboot -h, --help help for reboot
-l, --labels string Label(s) to filter desired baremetal host documents -l, --labels string Label(s) to filter desired baremetal host documents
--name string Name to filter desired baremetal host document --name string Name to filter desired baremetal host document

View File

@ -26,6 +26,8 @@ import (
// CommandOptions is used to store common variables from cmd flags for baremetal command group // CommandOptions is used to store common variables from cmd flags for baremetal command group
type CommandOptions struct { type CommandOptions struct {
All bool
Labels string Labels string
Name string Name string
Namespace string Namespace string
@ -42,12 +44,34 @@ func NewOptions(i ifc.Inventory) *CommandOptions {
} }
} }
func (o *CommandOptions) validateBMHAction() error {
if o.Name == "" && o.Namespace == "" && o.Labels == "" && !o.All {
return ErrInvalidOptions{Message: `must provide atleast one of the following options: ` +
`'name', 'namespace', 'labels' or 'all'`}
} else if o.All && (o.Name != "" || o.Namespace != "" || o.Labels != "") {
return ErrInvalidOptions{Message: "option 'all' can not be combined with other host selector options"}
}
return nil
}
func (o *CommandOptions) validateSingleHostAction() error {
if o.Name == "" && o.Namespace == "" && o.Labels == "" {
return ErrInvalidOptions{Message: "No options are specified, must provide atleast 'name', 'namespace' or 'labels'"}
}
return nil
}
// BMHAction performs an action against BaremetalHost objects // BMHAction performs an action against BaremetalHost objects
func (o *CommandOptions) BMHAction(op ifc.BaremetalOperation) error { func (o *CommandOptions) BMHAction(op ifc.BaremetalOperation) error {
if err := o.validateBMHAction(); err != nil {
return err
}
bmhInventory, err := o.Inventory.BaremetalInventory() bmhInventory, err := o.Inventory.BaremetalInventory()
if err != nil { if err != nil {
return err return err
} }
ctx, cancel := context.WithTimeout(context.Background(), o.Timeout) ctx, cancel := context.WithTimeout(context.Background(), o.Timeout)
defer cancel() defer cancel()
return bmhInventory.RunOperation( return bmhInventory.RunOperation(
@ -59,6 +83,9 @@ func (o *CommandOptions) BMHAction(op ifc.BaremetalOperation) error {
// RemoteDirect perform RemoteDirect operation against single host // RemoteDirect perform RemoteDirect operation against single host
func (o *CommandOptions) RemoteDirect() error { func (o *CommandOptions) RemoteDirect() error {
if err := o.validateSingleHostAction(); err != nil {
return err
}
host, err := o.getHost() host, err := o.getHost()
if err != nil { if err != nil {
return err return err
@ -70,6 +97,9 @@ func (o *CommandOptions) RemoteDirect() error {
// PowerStatus get power status of the single host // PowerStatus get power status of the single host
func (o *CommandOptions) PowerStatus(w io.Writer) error { func (o *CommandOptions) PowerStatus(w io.Writer) error {
if err := o.validateSingleHostAction(); err != nil {
return err
}
host, err := o.getHost() host, err := o.getHost()
if err != nil { if err != nil {
return err return err

View File

@ -20,6 +20,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/pkg/inventory" "opendev.org/airship/airshipctl/pkg/inventory"
"opendev.org/airship/airshipctl/pkg/inventory/ifc" "opendev.org/airship/airshipctl/pkg/inventory/ifc"
@ -28,6 +29,8 @@ import (
"opendev.org/airship/airshipctl/testutil/redfishutils" "opendev.org/airship/airshipctl/testutil/redfishutils"
) )
const testNode = "node-0"
func TestCommandOptions(t *testing.T) { func TestCommandOptions(t *testing.T) {
t.Run("error BMHAction bmh inventory", func(t *testing.T) { t.Run("error BMHAction bmh inventory", func(t *testing.T) {
inv := &mockinventory.MockInventory{} inv := &mockinventory.MockInventory{}
@ -35,10 +38,31 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(nil, expectedErr) inv.On("BaremetalInventory").Once().Return(nil, expectedErr)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.All = true
actualErr := co.BMHAction(ifc.BaremetalOperationPowerOn) actualErr := co.BMHAction(ifc.BaremetalOperationPowerOn)
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, expectedErr, actualErr)
}) })
t.Run("error BMHAction invalid empty options", func(t *testing.T) {
inv := &mockinventory.MockInventory{}
co := inventory.NewOptions(inv)
err := co.BMHAction(ifc.BaremetalOperationPowerOn)
require.Error(t, err)
assert.Contains(t, err.Error(), (inventory.ErrInvalidOptions{}).Error())
})
t.Run("error BMHAction invalid both all and other selectors", func(t *testing.T) {
inv := &mockinventory.MockInventory{}
co := inventory.NewOptions(inv)
co.All = true
co.Labels = "foo=bar"
err := co.BMHAction(ifc.BaremetalOperationPowerOn)
require.Error(t, err)
assert.Contains(t, err.Error(), (inventory.ErrInvalidOptions{}).Error())
})
t.Run("success BMHAction", func(t *testing.T) { t.Run("success BMHAction", func(t *testing.T) {
bmhInv := &mockinventory.MockBMHInventory{} bmhInv := &mockinventory.MockBMHInventory{}
bmhInv.On("RunOperation").Once().Return(nil) bmhInv.On("RunOperation").Once().Return(nil)
@ -47,6 +71,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(bmhInv, nil) inv.On("BaremetalInventory").Once().Return(bmhInv, nil)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.All = true
actualErr := co.BMHAction(ifc.BaremetalOperationPowerOn) actualErr := co.BMHAction(ifc.BaremetalOperationPowerOn)
assert.Equal(t, nil, actualErr) assert.Equal(t, nil, actualErr)
}) })
@ -60,6 +85,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(bmhInv, nil) inv.On("BaremetalInventory").Once().Return(bmhInv, nil)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
actualErr := co.PowerStatus(buf) actualErr := co.PowerStatus(buf)
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, expectedErr, actualErr)
@ -73,6 +99,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(nil, expectedErr) inv.On("BaremetalInventory").Once().Return(nil, expectedErr)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
actualErr := co.PowerStatus(buf) actualErr := co.PowerStatus(buf)
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, expectedErr, actualErr)
@ -91,6 +118,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(bmhInv, nil) inv.On("BaremetalInventory").Once().Return(bmhInv, nil)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
actualErr := co.PowerStatus(buf) actualErr := co.PowerStatus(buf)
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, expectedErr, actualErr)
@ -110,6 +138,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(bmhInv, nil) inv.On("BaremetalInventory").Once().Return(bmhInv, nil)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
actualErr := co.PowerStatus(buf) actualErr := co.PowerStatus(buf)
assert.Equal(t, nil, actualErr) assert.Equal(t, nil, actualErr)
@ -128,6 +157,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(bmhInv, nil) inv.On("BaremetalInventory").Once().Return(bmhInv, nil)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
co.IsoURL = "http://some-url" co.IsoURL = "http://some-url"
actualErr := co.RemoteDirect() actualErr := co.RemoteDirect()
assert.Equal(t, nil, actualErr) assert.Equal(t, nil, actualErr)
@ -144,6 +174,7 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(bmhInv, nil) inv.On("BaremetalInventory").Once().Return(bmhInv, nil)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
actualErr := co.RemoteDirect() actualErr := co.RemoteDirect()
// Simply check if error is returned in isoURL is not specified // Simply check if error is returned in isoURL is not specified
assert.Error(t, actualErr) assert.Error(t, actualErr)
@ -156,7 +187,29 @@ func TestCommandOptions(t *testing.T) {
inv.On("BaremetalInventory").Once().Return(nil, expectedErr) inv.On("BaremetalInventory").Once().Return(nil, expectedErr)
co := inventory.NewOptions(inv) co := inventory.NewOptions(inv)
co.Name = testNode
actualErr := co.RemoteDirect() actualErr := co.RemoteDirect()
assert.Equal(t, expectedErr, actualErr) assert.Equal(t, expectedErr, actualErr)
}) })
t.Run("error RemoteDirect invalid options", func(t *testing.T) {
inv := &mockinventory.MockInventory{}
co := inventory.NewOptions(inv)
err := co.RemoteDirect()
require.Error(t, err)
assert.Contains(t, err.Error(), (inventory.ErrInvalidOptions{}).Error())
})
t.Run("error RemoteDirect invalid options", func(t *testing.T) {
inv := &mockinventory.MockInventory{}
co := inventory.NewOptions(inv)
buf := bytes.NewBuffer([]byte{})
err := co.PowerStatus(buf)
require.Error(t, err)
assert.Contains(t, err.Error(), (inventory.ErrInvalidOptions{}).Error())
assert.Len(t, buf.Bytes(), 0)
})
} }

26
pkg/inventory/errors.go Normal file
View File

@ -0,0 +1,26 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package inventory
import "fmt"
// ErrInvalidOptions is returned when incompetible flags are
type ErrInvalidOptions struct {
Message string
}
func (e ErrInvalidOptions) Error() string {
return fmt.Sprintf("invalid options are supplied: %s", e.Message)
}

View File

@ -4,10 +4,10 @@ kind: BareMetalHost
metadata: metadata:
labels: labels:
airshipit.org/ephemeral-node: "true" airshipit.org/ephemeral-node: "true"
name: master-0 name: node-0
spec: spec:
online: true online: true
bootMACAddress: 00:3b:8b:0c:ec:8b bootMACAddress: 00:3b:8b:0c:ec:8b
bmc: bmc:
address: redfish+http://nolocalhost:32201/redfish/v1/Systems/ephemeral address: redfish+http://nolocalhost:32201/redfish/v1/Systems/ephemeral
credentialsName: master-0-bmc-secret credentialsName: node-0-bmc-secret