Implement RunAction method of the baremetal interface
Change-Id: I86b2cd7824c68ccd4fac875a5ad1d3ff9cd69072 Relates-To: #397 Relates-To: #362 Relates-To: #359
This commit is contained in:
parent
991fcdcd9e
commit
fa03b40f4a
@ -19,7 +19,6 @@ import (
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/config"
|
||||
"opendev.org/airship/airshipctl/pkg/document"
|
||||
"opendev.org/airship/airshipctl/pkg/errors"
|
||||
"opendev.org/airship/airshipctl/pkg/inventory/ifc"
|
||||
"opendev.org/airship/airshipctl/pkg/log"
|
||||
remoteifc "opendev.org/airship/airshipctl/pkg/remote/ifc"
|
||||
@ -89,7 +88,33 @@ func (i Inventory) RunOperation(
|
||||
op ifc.BaremetalOperation,
|
||||
selector ifc.BaremetalHostSelector,
|
||||
_ ifc.BaremetalBatchRunOptions) error {
|
||||
return errors.ErrNotImplemented{What: "RunOperation of the baremetal inventory interface"}
|
||||
log.Debugf("Running operation '%s' against hosts selected by selector '%v'", op, selector)
|
||||
|
||||
hostAction, err := action(ctx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hosts, err := i.Select(selector)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(hosts) == 0 {
|
||||
log.Printf("Filtering using selector %v' didn't return any hosts to perform operation '%s'", selector, op)
|
||||
return ErrNoBaremetalHostsFound{Selector: selector}
|
||||
}
|
||||
|
||||
// TODO add concurent action execution
|
||||
// TODO consider adding FailFast flag to BaremetalBatchRunOptions that would allow
|
||||
// not fail on first error, but accumulate errors and return them at the end.
|
||||
for _, host := range hosts {
|
||||
if hostErr := hostAction(host); hostErr != nil {
|
||||
return hostErr
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Host implements baremetal host interface
|
||||
@ -138,6 +163,29 @@ func (i Inventory) newHost(doc document.Document) (Host, error) {
|
||||
return Host{Client: client}, nil
|
||||
}
|
||||
|
||||
func action(ctx context.Context, op ifc.BaremetalOperation) (func(remoteifc.Client) error, error) {
|
||||
switch op {
|
||||
case ifc.BaremetalOperationReboot:
|
||||
return func(host remoteifc.Client) error {
|
||||
return host.RebootSystem(ctx)
|
||||
}, nil
|
||||
case ifc.BaremetalOperationPowerOff:
|
||||
return func(host remoteifc.Client) error {
|
||||
return host.SystemPowerOff(ctx)
|
||||
}, nil
|
||||
case ifc.BaremetalOperationPowerOn:
|
||||
return func(host remoteifc.Client) error {
|
||||
return host.SystemPowerOn(ctx)
|
||||
}, nil
|
||||
case ifc.BaremetalOperationEjectVirtualMedia:
|
||||
return func(host remoteifc.Client) error {
|
||||
return host.EjectVirtualMedia(ctx)
|
||||
}, nil
|
||||
default:
|
||||
return nil, ErrBaremetalOperationNotSupported{Operation: op}
|
||||
}
|
||||
}
|
||||
|
||||
func toDocumentSelector(selector ifc.BaremetalHostSelector) document.Selector {
|
||||
return document.NewSelector().
|
||||
ByKind(document.BareMetalHostKind).
|
||||
|
@ -15,6 +15,7 @@
|
||||
package baremetal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -119,6 +120,101 @@ func TestSelectOne(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunAction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, remoteDriver, expectedErr string
|
||||
operation ifc.BaremetalOperation
|
||||
|
||||
selector ifc.BaremetalHostSelector
|
||||
}{
|
||||
{
|
||||
name: "success return one host",
|
||||
remoteDriver: "redfish",
|
||||
operation: ifc.BaremetalOperation("not supported"),
|
||||
selector: (ifc.BaremetalHostSelector{}).ByName("master-0"),
|
||||
expectedErr: "Baremetal operation not supported",
|
||||
},
|
||||
{
|
||||
name: "success return one host",
|
||||
remoteDriver: "redfish",
|
||||
operation: ifc.BaremetalOperationPowerOn,
|
||||
selector: (ifc.BaremetalHostSelector{}).ByName("does not exist"),
|
||||
expectedErr: "No baremetal hosts matched selector",
|
||||
},
|
||||
{
|
||||
name: "success return one host",
|
||||
remoteDriver: "redfish",
|
||||
operation: ifc.BaremetalOperationPowerOn,
|
||||
selector: (ifc.BaremetalHostSelector{}).ByName("master-0"),
|
||||
expectedErr: "HTTP request failed",
|
||||
},
|
||||
}
|
||||
|
||||
bundle := testBundle(t)
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mgmCfg := config.ManagementConfiguration{Type: tt.remoteDriver}
|
||||
inventory := NewInventory(mgmCfg, bundle)
|
||||
err := inventory.RunOperation(
|
||||
context.Background(),
|
||||
tt.operation,
|
||||
tt.selector,
|
||||
ifc.BaremetalBatchRunOptions{})
|
||||
if tt.expectedErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.expectedErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
action ifc.BaremetalOperation
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "poweron",
|
||||
action: ifc.BaremetalOperationPowerOn,
|
||||
},
|
||||
{
|
||||
name: "poweroff",
|
||||
action: ifc.BaremetalOperationPowerOff,
|
||||
},
|
||||
{
|
||||
name: "ejectvirtualmedia",
|
||||
action: ifc.BaremetalOperationEjectVirtualMedia,
|
||||
},
|
||||
{
|
||||
name: "reboot",
|
||||
action: ifc.BaremetalOperationReboot,
|
||||
},
|
||||
{
|
||||
name: "reboot",
|
||||
action: ifc.BaremetalOperation("not supported"),
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actionFunc, err := action(context.Background(), tt.action)
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
// TODO inject fake host interface here to validate
|
||||
// that correct actions were selected
|
||||
assert.NotNil(t, actionFunc)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testBundle(t *testing.T) document.Bundle {
|
||||
t.Helper()
|
||||
bundle, err := document.NewBundleByPath("testdata")
|
||||
|
@ -40,3 +40,12 @@ type ErrNoBaremetalHostsFound struct {
|
||||
func (e ErrNoBaremetalHostsFound) Error() string {
|
||||
return fmt.Sprintf("No baremetal hosts matched selector %v", e.Selector)
|
||||
}
|
||||
|
||||
// ErrBaremetalOperationNotSupported is returned when baremetal operation is not supported
|
||||
type ErrBaremetalOperationNotSupported struct {
|
||||
Operation ifc.BaremetalOperation
|
||||
}
|
||||
|
||||
func (e ErrBaremetalOperationNotSupported) Error() string {
|
||||
return fmt.Sprintf("Baremetal operation not supported: '%s'", e.Operation)
|
||||
}
|
||||
|
2
pkg/inventory/baremetal/testdata/hosts.yaml
vendored
2
pkg/inventory/baremetal/testdata/hosts.yaml
vendored
@ -9,7 +9,7 @@ spec:
|
||||
online: true
|
||||
bootMACAddress: 00:3b:8b:0c:ec:8b
|
||||
bmc:
|
||||
address: redfish+http://nolocalhost:8888/redfish/v1/Systems/ephemeral
|
||||
address: redfish+http://nolocalhost:32201/redfish/v1/Systems/ephemeral
|
||||
credentialsName: master-0-bmc-secret
|
||||
---
|
||||
apiVersion: v1
|
||||
|
Loading…
Reference in New Issue
Block a user