Fix power command host selectors

Both host selectors are always passed to create a manager when a power
command is invoked; however, an empty label selector will include all
hosts.

This change adds a helper function to determine which selectors will be
used based on the flags passed to airshipctl. When a flag is not used, a
selector is not created for it.

Change-Id: I48684cdf6d16073bf85468f6286a22a0aba602f7
Signed-off-by: Drew Walters <andrew.walters@att.com>
This commit is contained in:
Drew Walters 2020-05-01 16:26:26 +00:00
parent 54d7b5f229
commit 4b6d2328de
10 changed files with 61 additions and 5 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/remote"
)
const (
@ -63,3 +64,18 @@ func NewBaremetalCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Co
return cmd
}
// getHostSelections builds a list of selectors that can be passed to a manager using the name and label flags passed to
// airshipctl.
func GetHostSelections(name string, labels string) []remote.HostSelector {
var selectors []remote.HostSelector
if name != "" {
selectors = append(selectors, remote.ByName(name))
}
if labels != "" {
selectors = append(selectors, remote.ByLabel(labels))
}
return selectors
}

View File

@ -17,6 +17,8 @@ package baremetal_test
import (
"testing"
"github.com/stretchr/testify/assert"
"opendev.org/airship/airshipctl/cmd/baremetal"
"opendev.org/airship/airshipctl/testutil"
)
@ -69,3 +71,18 @@ func TestBaremetal(t *testing.T) {
testutil.RunTest(t, tt)
}
}
func TestGetHostSelectionsOneSelector(t *testing.T) {
selectors := baremetal.GetHostSelections("node0", "")
assert.Len(t, selectors, 1)
}
func TestGetHostSelectionsBothSelectors(t *testing.T) {
selectors := baremetal.GetHostSelections("node0", "airshipit.org/ephemeral-node=true")
assert.Len(t, selectors, 2)
}
func TestGetHostSelectionsNone(t *testing.T) {
selectors := baremetal.GetHostSelections("", "")
assert.Len(t, selectors, 0)
}

View File

@ -35,7 +35,8 @@ func NewEjectMediaCommand(rootSettings *environment.AirshipCTLSettings) *cobra.C
Short: "Eject media attached to a baremetal host",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByLabel(labels), remote.ByName(name))
selectors := GetHostSelections(name, labels)
m, err := remote.NewManager(rootSettings, phase, selectors...)
if err != nil {
return err
}

View File

@ -35,7 +35,8 @@ func NewPowerOffCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Com
Short: "Shutdown a baremetal host",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByLabel(labels), remote.ByName(name))
selectors := GetHostSelections(name, labels)
m, err := remote.NewManager(rootSettings, phase, selectors...)
if err != nil {
return err
}

View File

@ -35,7 +35,8 @@ func NewPowerOnCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comm
Short: "Power on a host",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByLabel(labels), remote.ByName(name))
selectors := GetHostSelections(name, labels)
m, err := remote.NewManager(rootSettings, phase, selectors...)
if err != nil {
return err
}

View File

@ -35,7 +35,8 @@ func NewPowerStatusCommand(rootSettings *environment.AirshipCTLSettings) *cobra.
Short: "Retrieve the power status of a baremetal host",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByLabel(labels), remote.ByName(name))
selectors := GetHostSelections(name, labels)
m, err := remote.NewManager(rootSettings, phase, selectors...)
if err != nil {
return err
}

View File

@ -35,7 +35,8 @@ func NewRebootCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
Short: "Reboot a host",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByLabel(labels), remote.ByName(name))
selectors := GetHostSelections(name, labels)
m, err := remote.NewManager(rootSettings, phase, selectors...)
if err != nil {
return err
}

View File

@ -56,3 +56,10 @@ type ErrMissingBootstrapInfoOption struct {
func (e ErrMissingBootstrapInfoOption) Error() string {
return fmt.Sprintf("missing bootstrapInfo option: %s", e.What)
}
// ErrNoHostsFound is an error that indicates that no hosts matched the selection criteria passed to a manager.
type ErrNoHostsFound struct{}
func (e ErrNoHostsFound) Error() string {
return "no hosts selected"
}

View File

@ -146,6 +146,10 @@ func NewManager(settings *environment.AirshipCTLSettings, phase string, hosts ..
}
}
if len(manager.Hosts) == 0 {
return manager, ErrNoHostsFound{}
}
return manager, nil
}

View File

@ -102,6 +102,13 @@ func TestNewManagerByNameNoHostFound(t *testing.T) {
assert.Error(t, err)
}
func TestNewManagerNoSelectors(t *testing.T) {
settings := initSettings(t, withTestDataPath("base"))
_, err := NewManager(settings, config.BootstrapPhase)
assert.Error(t, err)
}
func TestNewManagerByLabelNoHostsFound(t *testing.T) {
settings := initSettings(t, withTestDataPath("base"))