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/config"
|
||||||
"opendev.org/airship/airshipctl/pkg/document"
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
"opendev.org/airship/airshipctl/pkg/errors"
|
|
||||||
"opendev.org/airship/airshipctl/pkg/inventory/ifc"
|
"opendev.org/airship/airshipctl/pkg/inventory/ifc"
|
||||||
"opendev.org/airship/airshipctl/pkg/log"
|
"opendev.org/airship/airshipctl/pkg/log"
|
||||||
remoteifc "opendev.org/airship/airshipctl/pkg/remote/ifc"
|
remoteifc "opendev.org/airship/airshipctl/pkg/remote/ifc"
|
||||||
@ -89,7 +88,33 @@ func (i Inventory) RunOperation(
|
|||||||
op ifc.BaremetalOperation,
|
op ifc.BaremetalOperation,
|
||||||
selector ifc.BaremetalHostSelector,
|
selector ifc.BaremetalHostSelector,
|
||||||
_ ifc.BaremetalBatchRunOptions) error {
|
_ 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
|
// Host implements baremetal host interface
|
||||||
@ -138,6 +163,29 @@ func (i Inventory) newHost(doc document.Document) (Host, error) {
|
|||||||
return Host{Client: client}, nil
|
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 {
|
func toDocumentSelector(selector ifc.BaremetalHostSelector) document.Selector {
|
||||||
return document.NewSelector().
|
return document.NewSelector().
|
||||||
ByKind(document.BareMetalHostKind).
|
ByKind(document.BareMetalHostKind).
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package baremetal
|
package baremetal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"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 {
|
func testBundle(t *testing.T) document.Bundle {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
bundle, err := document.NewBundleByPath("testdata")
|
bundle, err := document.NewBundleByPath("testdata")
|
||||||
|
@ -40,3 +40,12 @@ type ErrNoBaremetalHostsFound struct {
|
|||||||
func (e ErrNoBaremetalHostsFound) Error() string {
|
func (e ErrNoBaremetalHostsFound) Error() string {
|
||||||
return fmt.Sprintf("No baremetal hosts matched selector %v", e.Selector)
|
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
|
online: true
|
||||||
bootMACAddress: 00:3b:8b:0c:ec:8b
|
bootMACAddress: 00:3b:8b:0c:ec:8b
|
||||||
bmc:
|
bmc:
|
||||||
address: redfish+http://nolocalhost:8888/redfish/v1/Systems/ephemeral
|
address: redfish+http://nolocalhost:32201/redfish/v1/Systems/ephemeral
|
||||||
credentialsName: master-0-bmc-secret
|
credentialsName: master-0-bmc-secret
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
Loading…
Reference in New Issue
Block a user