Skip to content

Commit 7a8fe80

Browse files
committed
feat: Implement basic structures and testing
This commit provides the basic framework, interfaces and some tests as example for futher extention. Signed-off-by: Christopher Meis <christopher.meis@9elements.com>
1 parent 8d563eb commit 7a8fe80

File tree

27 files changed

+1433
-100
lines changed

27 files changed

+1433
-100
lines changed

Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ tasks:
1212
matrix:
1313
OS: ['linux']
1414
ARCH: ['amd64', 'arm', 'arm64']
15-
cmd: GOOS="{{.ITEM.OS}}" GOARCH="{{.ITEM.ARCH}}" go build -ldflags="-s -w" -o "bin/bmc-test-go-{{.ITEM.OS}}-{{.ITEM.ARCH}}-{{.SEMVER}}"
15+
cmd: GOOS="{{.ITEM.OS}}" GOARCH="{{.ITEM.ARCH}}" go build -ldflags="-s -w" -o "bin/bmc-test-go-{{.ITEM.OS}}-{{.ITEM.ARCH}}-{{.SEMVER}}" ./cmds/openbmc-tests
1616

1717
lint:
1818
desc: Run linters

cmds/openbmc-tests/cmdline.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
)
6+
7+
var (
8+
runSingleCmd string = "single"
9+
runSuiteCmd string = "suite"
10+
runAllCmd string = "run-all"
11+
cfgCheckCmd string = "cfg-check"
12+
)
13+
14+
type flags struct {
15+
cmd string
16+
configPath string
17+
execEnv string
18+
testName string
19+
logType string
20+
logFile string
21+
}
22+
23+
func parseFlags(args []string) (*flags, error) {
24+
f := &flags{
25+
cmd: args[0],
26+
}
27+
28+
cfgCheckFS := flag.NewFlagSet(cfgCheckCmd, flag.ExitOnError)
29+
cfgCheckFS.StringVar(&f.configPath, "config", "contrib/example_config.yaml", "Path to device specific test case configuration file")
30+
31+
runSingleFS := flag.NewFlagSet("run-single", flag.ExitOnError)
32+
runSingleFS.StringVar(&f.testName, "testname", "", "Run a single test with 'testname'. No default")
33+
runSingleFS.StringVar(&f.execEnv, "exec-env", "remote", "Run the test locally or remotely '<local, remote>'. Default: remote")
34+
runSingleFS.StringVar(&f.configPath, "config", "contrib/example_config.yaml", "Path to device specific test case configuration file")
35+
runSingleFS.StringVar(&f.logType, "log", "default", "Logging options <default, structured>")
36+
runSingleFS.StringVar(&f.logFile, "logfile", "", "Path to log file. Only with structured logging option.")
37+
38+
runSuiteFS := flag.NewFlagSet("suite", flag.ExitOnError)
39+
runSuiteFS.StringVar(&f.execEnv, "exec-env", "remote", "Run the test locally or remotely '<local, remote>'. Default: remote")
40+
runSuiteFS.StringVar(&f.configPath, "config", "contrib/example_config.yaml", "Path to device specific test case configuration file")
41+
runSuiteFS.StringVar(&f.logType, "log", "default", "Logging options <default, structured>")
42+
runSuiteFS.StringVar(&f.logFile, "logfile", "", "Path to log file. Only with structured logging option.")
43+
runAllFS := flag.NewFlagSet("run-all", flag.ExitOnError)
44+
runAllFS.StringVar(&f.execEnv, "exec-env", "remote", "Run the test locally or remotely '<local, remote>'.")
45+
runAllFS.StringVar(&f.configPath, "config", "contrib/example_config.yaml", "Path to device specific test case configuration file")
46+
runAllFS.StringVar(&f.logType, "log", "default", "Logging options <default, structured>")
47+
runAllFS.StringVar(&f.logFile, "logfile", "", "Path to log file. Only with structured logging option.")
48+
49+
var err error
50+
switch args[0] {
51+
case cfgCheckCmd:
52+
err = cfgCheckFS.Parse(args[1:])
53+
case runSingleCmd:
54+
err = runSingleFS.Parse(args[1:])
55+
case runSuiteCmd:
56+
err = runSuiteFS.Parse(args[1:])
57+
case runAllCmd:
58+
err = runAllFS.Parse(args[1:])
59+
default:
60+
cfgCheckFS.Usage()
61+
runSingleFS.Usage()
62+
runSuiteFS.Usage()
63+
runAllFS.Usage()
64+
}
65+
if err != nil {
66+
return nil, err
67+
}
68+
69+
return f, nil
70+
}

cmds/openbmc-tests/main.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
3+
// Package main implements the core logic
4+
package main
5+
6+
import (
7+
"fmt"
8+
"log"
9+
"os"
10+
11+
"github.com/9elements/bmc-test-go/pkg/bmc"
12+
"github.com/9elements/bmc-test-go/pkg/configuration"
13+
"github.com/9elements/bmc-test-go/pkg/framework"
14+
"github.com/9elements/bmc-test-go/pkg/tests"
15+
"github.com/9elements/bmc-test-go/pkg/tests/ipmi"
16+
)
17+
18+
func runAll(bmc *bmc.BMC, cfg *configuration.Config) error {
19+
ipmiPre := &ipmi.IPMISDRPrecondition{}
20+
if err := ipmiPre.Run(bmc); err != nil {
21+
return err
22+
}
23+
24+
tests := tests.AllTests()
25+
if len(tests) < 1 {
26+
return fmt.Errorf("no tests to execute")
27+
}
28+
29+
for _, test := range tests {
30+
if !framework.RunTest(test, bmc, cfg, ipmiPre) {
31+
log.Printf("test: %s failed: %s", test.Name(), test.ErrorText())
32+
continue
33+
}
34+
}
35+
return nil
36+
}
37+
38+
func runSingle(testname string, bmc *bmc.BMC, cfg *configuration.Config) error {
39+
ipmiPre := &ipmi.IPMISDRPrecondition{}
40+
if err := ipmiPre.Run(bmc); err != nil {
41+
return err
42+
}
43+
44+
tests := tests.AllTests()
45+
if len(tests) < 1 {
46+
return fmt.Errorf("no tests to execute")
47+
}
48+
49+
for _, test := range tests {
50+
if test.Name() == testname {
51+
if !framework.RunTest(test, bmc, cfg, ipmiPre) {
52+
return fmt.Errorf("%s", test.ErrorText())
53+
}
54+
}
55+
}
56+
57+
return nil
58+
}
59+
60+
func runSuite(suite string, bmc *bmc.BMC, cfg *configuration.Config) error {
61+
ipmiPre := &ipmi.IPMISDRPrecondition{}
62+
if err := ipmiPre.Run(bmc); err != nil {
63+
return err
64+
}
65+
66+
tests := tests.GetSuite(suite)
67+
if len(tests) < 1 {
68+
return fmt.Errorf("no tests to execute")
69+
}
70+
71+
for _, test := range tests {
72+
if !framework.RunTest(test, bmc, cfg, ipmiPre) {
73+
return fmt.Errorf("%s", test.ErrorText())
74+
}
75+
}
76+
return nil
77+
}
78+
79+
func run() error {
80+
flags, err := parseFlags(os.Args[1:])
81+
if err != nil {
82+
return err
83+
}
84+
85+
cfg, err := configuration.LoadConfig(flags.configPath)
86+
if err != nil {
87+
return err
88+
}
89+
90+
if err := framework.SetupReporting(flags.logType, flags.logFile); err != nil {
91+
return err
92+
}
93+
94+
switch flags.cmd {
95+
case runSingleCmd:
96+
bmc, err := bmc.NewBMC(flags.execEnv, cfg)
97+
if err != nil {
98+
return err
99+
}
100+
defer func() {
101+
if err := bmc.Close(); err != nil {
102+
log.Print(err)
103+
}
104+
}()
105+
return runSingle(flags.testName, bmc, cfg)
106+
case runSuiteCmd:
107+
bmc, err := bmc.NewBMC(flags.execEnv, cfg)
108+
if err != nil {
109+
return err
110+
}
111+
defer func() {
112+
if err := bmc.Close(); err != nil {
113+
log.Print(err)
114+
}
115+
}()
116+
return runSuite(flags.testName, bmc, cfg)
117+
case runAllCmd:
118+
bmc, err := bmc.NewBMC(flags.execEnv, cfg)
119+
if err != nil {
120+
return err
121+
}
122+
defer func() {
123+
if err := bmc.Close(); err != nil {
124+
log.Print(err)
125+
}
126+
}()
127+
return runAll(bmc, cfg)
128+
case cfgCheckCmd:
129+
return configuration.Validate(cfg)
130+
default:
131+
return fmt.Errorf("unknown command: %s", flags.cmd)
132+
}
133+
}
134+
135+
func main() {
136+
if err := run(); err != nil {
137+
log.Print(err)
138+
os.Exit(1)
139+
}
140+
}

contrib/example_config.yaml

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,43 @@
11
---
22
version: 0
33
name: ExampleServer
4-
requirements:
5-
redfish:
6-
general:
7-
cpuvendor: "TestVendor"
8-
cpumodel: TestModel
9-
psucount: 0
10-
voltage:
11-
- TestString 1
12-
- TestString 2
13-
temperatures:
14-
- Test Temp 1
15-
- Test Temp 2
16-
fans:
17-
- Test Fans 1
18-
- Test Fans 2
19-
dimms:
4+
bm_config:
5+
bmc_host: bmcIP
6+
bmc_user: root
7+
bmc_password: 0penBmc
8+
ssh_port: "22"
9+
numHosts: 1
10+
hosts:
11+
- host1:
12+
ip: hostIP1
13+
user: hostUser1
14+
password: hostPassword1
15+
- host2:
16+
ip: hostIP2
17+
user: hostUser2
18+
password: hostPassword2
19+
testdata:
20+
system:
21+
guid: guid-string
22+
cpu:
23+
cpuvendor: ""
24+
cpumodel: ""
25+
voltage:
26+
- TestString 1
27+
- TestString 2
28+
temperatures:
29+
- Test Temp 1
30+
- Test Temp 2
31+
fans:
32+
- Test Fans 1
33+
- Test Fans 2
34+
dimms:
2035
count: 0
2136
partNo: 0123
2237
vendor: TestDimmmVendor
2338
capacity: 1336
2439
fru:
25-
fruExpected:
26-
vendor: TestFruVendor
27-
name: TestFruName
28-
serial: TestSerial001
40+
- productManufacturer: TestVal
41+
productName: 'testName'
42+
productSerial: 'testSerial'
43+
boardManufacturer: testManufacturer

go.mod

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
module github.com/9elements/bmc-test-go
22

3-
go 1.23
3+
go 1.25.0
44

5-
require gopkg.in/yaml.v3 v3.0.1
5+
require (
6+
github.com/sirupsen/logrus v1.9.4
7+
github.com/stmcginnis/gofish v0.20.0
8+
golang.org/x/crypto v0.47.0
9+
gopkg.in/yaml.v3 v3.0.1
10+
)
11+
12+
require golang.org/x/sys v0.40.0 // indirect

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
6+
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
7+
github.com/stmcginnis/gofish v0.20.0 h1:hH2V2Qe898F2wWT1loApnkDUrXXiLKqbSlMaH3Y1n08=
8+
github.com/stmcginnis/gofish v0.20.0/go.mod h1:PzF5i8ecRG9A2ol8XT64npKUunyraJ+7t0kYMpQAtqU=
9+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
10+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
11+
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
12+
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
13+
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
14+
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
15+
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
16+
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
117
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
218
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
319
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

main.go

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)