Add run subcommand (#529)
* test: fix TestGetConfigFilePath This test wasn't correctly creating the test file due to the wrong directory permissions on the temp file. This wasn't detected due to a lack of error checking. Also, the code was only checking for file not exist rather than lack of permission to read file (or any other error). The combination of these two things means the test wasn't checking what it thought it was checking, and passed more by luck than judgment. * add getYamlFilesFromDir * add getTestYamlFiles and test * docs: Update master / node help text * return path + filename from getYamlFilesFromDir * subcommand run to run specific section filespull/527/head^2
parent
8780e5cb59
commit
f2caa1f0ec
@ -0,0 +1,91 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/aquasecurity/kube-bench/check"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RootCmd.AddCommand(runCmd)
|
||||||
|
runCmd.Flags().StringSliceP("sections", "s", []string{},
|
||||||
|
`Specify sections of the benchmark to run. These names need to match the filenames in the cfg/<version> directory.
|
||||||
|
For example, to run the tests specified in master.yaml and etcd.yaml, specify --sections=master,etcd
|
||||||
|
If no sections are specified, run tests from all files in the cfg/<version> directory.
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// runCmd represents the run command
|
||||||
|
var runCmd = &cobra.Command{
|
||||||
|
Use: "run",
|
||||||
|
Short: "Run tests",
|
||||||
|
Long: `Run tests. If no arguments are specified, runs tests from all files`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
sections, err := cmd.Flags().GetStringSlice("sections")
|
||||||
|
if err != nil {
|
||||||
|
exitWithError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmarkVersion, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, viper.GetViper())
|
||||||
|
if err != nil {
|
||||||
|
exitWithError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge version-specific config if any.
|
||||||
|
path := filepath.Join(cfgDir, benchmarkVersion)
|
||||||
|
mergeConfig(path)
|
||||||
|
|
||||||
|
err = run(sections, benchmarkVersion)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error in run: %v\n", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(sections []string, benchmarkVersion string) (err error) {
|
||||||
|
|
||||||
|
yamlFiles, err := getTestYamlFiles(sections, benchmarkVersion)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(3).Infof("Running tests from files %v\n", yamlFiles)
|
||||||
|
|
||||||
|
for _, yamlFile := range yamlFiles {
|
||||||
|
_, name := filepath.Split(yamlFile)
|
||||||
|
testType := check.NodeType(strings.Split(name, ".")[0])
|
||||||
|
runChecks(testType, yamlFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestYamlFiles(sections []string, benchmarkVersion string) (yamlFiles []string, err error) {
|
||||||
|
|
||||||
|
// Check that the specified sections have corresponding YAML files in the config directory
|
||||||
|
configFileDirectory := filepath.Join(cfgDir, benchmarkVersion)
|
||||||
|
for _, section := range sections {
|
||||||
|
filename := section + ".yaml"
|
||||||
|
file := filepath.Join(configFileDirectory, filename)
|
||||||
|
if _, err := os.Stat(file); err != nil {
|
||||||
|
return nil, fmt.Errorf("file %s not found for version %s", filename, benchmarkVersion)
|
||||||
|
}
|
||||||
|
yamlFiles = append(yamlFiles, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no sections were specified, we will run tests from all the files in the directory
|
||||||
|
if len(yamlFiles) == 0 {
|
||||||
|
yamlFiles, err = getYamlFilesFromDir(configFileDirectory)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return yamlFiles, err
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetTestYamlFiles(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
sections []string
|
||||||
|
benchmark string
|
||||||
|
succeed bool
|
||||||
|
expCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Specify two sections",
|
||||||
|
sections: []string{"one", "two"},
|
||||||
|
benchmark: "benchmark",
|
||||||
|
succeed: true,
|
||||||
|
expCount: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Specify a section that doesn't exist",
|
||||||
|
sections: []string{"one", "missing"},
|
||||||
|
benchmark: "benchmark",
|
||||||
|
succeed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "No sections specified - should return everything except config.yaml",
|
||||||
|
sections: []string{},
|
||||||
|
benchmark: "benchmark",
|
||||||
|
succeed: true,
|
||||||
|
expCount: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Specify benchmark that doesn't exist",
|
||||||
|
sections: []string{"one"},
|
||||||
|
benchmark: "missing",
|
||||||
|
succeed: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up temp config directory
|
||||||
|
var err error
|
||||||
|
cfgDir, err = ioutil.TempDir("", "kube-bench-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp directory")
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(cfgDir)
|
||||||
|
|
||||||
|
d := filepath.Join(cfgDir, "benchmark")
|
||||||
|
err = os.Mkdir(d, 0766)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We never expect config.yaml to be returned
|
||||||
|
for _, filename := range []string{"one.yaml", "two.yaml", "three.yaml", "config.yaml"} {
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, filename), []byte("hello world"), 0666)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error writing temp file %s: %v", filename, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
yamlFiles, err := getTestYamlFiles(c.sections, c.benchmark)
|
||||||
|
if err != nil && c.succeed {
|
||||||
|
t.Fatalf("Error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && !c.succeed {
|
||||||
|
t.Fatalf("Expected failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(yamlFiles) != c.expCount {
|
||||||
|
t.Fatalf("Expected %d, got %d", c.expCount, len(yamlFiles))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue