diff --git a/Dockerfile b/Dockerfile
index 8f875476..af44e2d3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -11,7 +11,7 @@ RUN CGO_ENABLED=0 \
-ldflags="-w -s -extldflags '-static' -X github.com/Boeing/config-file-validator.version=$VALIDATOR_VERSION" \
-tags netgo \
-o validator \
- cmd/validator/validator.go
+ main.go
FROM $BASE_IMAGE
COPY --from=go-builder /build/validator /
diff --git a/README.md b/README.md
index 1fd0db24..34f3d36a 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,6 @@
-
-
-
-
@@ -31,9 +27,7 @@
## Supported config files formats:
* Apple PList XML
* CSV
-* ENV
* HCL
-* HOCON
* INI
* JSON
* Properties
@@ -97,28 +91,28 @@ go install github.com/Boeing/config-file-validator/cmd/validator@v1.6.0
## Usage
```
-Usage: validator [OPTIONS] [...]
-
-positional arguments:
- search_path: The search path on the filesystem for configuration files. Defaults to the current working directory if no search_path provided
-
-optional flags:
- -depth int
- Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal
- -exclude-dirs string
- Subdirectories to exclude when searching for configuration files
- -exclude-file-types string
- A comma separated list of file types to ignore
- -groupby string
- Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
- -output string
- Destination to a file to output results
- -quiet
- If quiet flag is set. It doesn't print any output to stdout.
- -reporter string
- Format of the printed report. Options are standard and json (default "standard")
- -version
- Version prints the release version of validator
+Cross Platform tool to validate configuration files
+
+Usage:
+ validator [flags]
+ validator [command]
+
+Available Commands:
+ completion Generate the autocompletion script for the specified shell
+ help Help about any command
+ version Version prints the release version of validator
+
+Flags:
+ --depth int Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal.
+ --exclude-dirs string Subdirectories to exclude when searching for configuration files
+ --exclude-file-types string A comma separated list of file types to ignore
+ --groupby string Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
+ -h, --help help for validator
+ --output string Destination to a file to output results
+ --quiet If quiet flag is set. It doesn't print any output to stdout.
+ --reporter string Format of the printed report. Options are standard and json (default "standard")
+
+Use "validator [command] --help" for more information about a command.
```
### Examples
@@ -190,6 +184,7 @@ validator -groupby directory,pass-fail
![Groupby File Type and Pass/Fail](./img/gb-filetype-and-pass-fail.png)
+
### Output results to a file
Output report results to a file (default name is `result.{extension}`). Must provide reporter flag with a supported extension format. Available options are `junit` and `json`. If an existing directory is provided, create a file named default name in the given directory. If a file name is provided, create a file named the given name at the current working directory.
@@ -224,7 +219,7 @@ go build \
-ldflags='-w -s -extldflags "-static"' \
-tags netgo \
-o validator \
-cmd/validator/validator.go
+main.go
```
#### Install
@@ -243,7 +238,7 @@ go build \
-ldflags='-w -s -extldflags "-static"' \
-tags netgo \
-o validator \
-cmd/validator/validator.go
+main.go
```
#### Install
@@ -262,7 +257,7 @@ go build \
-ldflags='-w -s -extldflags "-static"' \
-tags netgo \
-o validator.exe \
-cmd/validator/validator.go
+main.go
```
#### Install
diff --git a/cmd/validator/commands/flags.go b/cmd/validator/commands/flags.go
new file mode 100644
index 00000000..24be4c58
--- /dev/null
+++ b/cmd/validator/commands/flags.go
@@ -0,0 +1,26 @@
+package cmd
+
+import (
+ validator "github.com/Boeing/config-file-validator/cmd/validator"
+ "github.com/spf13/cobra"
+)
+
+func CmdFlags(cmd *cobra.Command) {
+ cmd.PersistentFlags().
+ IntVar(&validator.Flags.Depth, "depth", 0, "Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal.")
+ cmd.PersistentFlags().
+ StringVar(&validator.Flags.ExcludeDirs, "exclude-dirs", "", "Subdirectories to exclude when searching for configuration files")
+ cmd.PersistentFlags().
+ StringVar(&validator.Flags.ExcludeFileTypes, "exclude-file-types", "", "A comma separated list of file types to ignore")
+ cmd.PersistentFlags().StringVar(&validator.Flags.Output, "output", "", "Destination to a file to output results")
+ cmd.PersistentFlags().
+ StringVar(&validator.Flags.ReportType, "reporter", "standard", "Format of the printed report. Options are standard and json")
+ cmd.PersistentFlags().
+ StringVar(&validator.Flags.GroupOutput, "groupby", "", "Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports")
+ cmd.PersistentFlags().
+ BoolVar(&validator.Flags.Quiet, "quiet", false, "If quiet flag is set. It doesn't print any output to stdout.")
+}
+
+func init() {
+ CmdFlags(rootCmd)
+}
diff --git a/cmd/validator/commands/flags_test.go b/cmd/validator/commands/flags_test.go
new file mode 100644
index 00000000..5bca2b46
--- /dev/null
+++ b/cmd/validator/commands/flags_test.go
@@ -0,0 +1,73 @@
+package cmd
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+
+ cmd "github.com/Boeing/config-file-validator/cmd/validator"
+ "github.com/spf13/cobra"
+)
+
+func ExecuteTestHelper(t *testing.T, c *cobra.Command, args ...string) (string, error) {
+ t.Helper()
+
+ buf := new(bytes.Buffer)
+ c.SetOut(buf)
+ c.SetErr(buf)
+ c.SetArgs(args)
+
+ err := c.Execute()
+ return strings.TrimSpace(buf.String()), err
+}
+
+func Test_flags(t *testing.T) {
+ // We manipulate the Args to set them up for the testcases
+ cases := []struct {
+ Name string
+ Args []string
+ ExpectedExit int
+ }{
+ {"blank", []string{}, 0},
+ {"negative depth set", []string{"--depth", "-1", "--reporter", "standard"}, 1},
+ {"flags set, wrong reporter", []string{"--exclude-dirs", "subdir", "--reporter", "wrong"}, 1},
+ {"flags set, json reporter", []string{"--exclude-dirs", "subdir", "--reporter", "json"}, 0},
+ {"flags set, junit reported", []string{"--exclude-dirs", "subdir", "--reporter", "junit"}, 0},
+ {"bad path", []string{"/path/does/not/exit"}, 1},
+ {"exclude file types set", []string{"--exclude-file-types", "json"}, 0},
+ {"multiple paths", []string{"../../../test/fixtures/subdir/good.json", "../../../test/fixtures/good.json"}, 0},
+ {"output set", []string{"--output", "../../../test/output", "--reporter", "json"}, 0},
+
+ {"empty string output set", []string{"--output", "", "--reporter", "json", "."}, 0},
+ {"wrong output set", []string{"--output", "/path/not/exist", "--reporter", "json", "."}, 1},
+ {"incorrect group", []string{"--groupby", "badgroup"}, 1},
+ {"correct group", []string{"--groupby", "directory"}, 0},
+ {"grouped junit", []string{"--groupby", "directory", "--reporter", "junit", "."}, 1},
+ {"groupby duplicate", []string{"--groupby", "directory,directory", "."}, 1},
+ {"quiet flag", []string{"--quiet", "."}, 0},
+ }
+
+ var exitStatus int
+
+ for _, tc := range cases {
+ root := &cobra.Command{
+ Use: "root",
+ Run: func(c *cobra.Command, args []string) {
+ exitStatus = cmd.ExecRoot(c, args)
+ },
+ }
+ CmdFlags(root)
+
+ t.Run(tc.Name, func(t *testing.T) {
+ _, err := ExecuteTestHelper(t, root, tc.Args...)
+ if err != nil {
+ t.Error("ExecuteTestHelper: ", err)
+ }
+
+ if tc.ExpectedExit != exitStatus {
+ t.Errorf("Wrong exit code, expected: %v, got: %v", tc.ExpectedExit, exitStatus)
+ }
+ })
+ }
+
+}
diff --git a/cmd/validator/commands/root.go b/cmd/validator/commands/root.go
new file mode 100644
index 00000000..1089a4c0
--- /dev/null
+++ b/cmd/validator/commands/root.go
@@ -0,0 +1,26 @@
+package cmd
+
+import (
+ "fmt"
+ "os"
+
+ validator "github.com/Boeing/config-file-validator/cmd/validator"
+ "github.com/spf13/cobra"
+)
+
+// rootCmd command configuration and setup
+var rootCmd = &cobra.Command{
+ Use: "validator",
+ Short: "Cross Platform tool to validate configuration files",
+ Args: cobra.ArbitraryArgs,
+ Run: func(cmd *cobra.Command, args []string) {
+ os.Exit(validator.ExecRoot(cmd, args))
+ },
+}
+
+func Execute() {
+ if err := rootCmd.Execute(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
diff --git a/version.go b/cmd/validator/commands/version.go
similarity index 53%
rename from version.go
rename to cmd/validator/commands/version.go
index 56eaa212..8bf8db96 100644
--- a/version.go
+++ b/cmd/validator/commands/version.go
@@ -1,6 +1,10 @@
-package configfilevalidator
+package cmd
-import "fmt"
+import (
+ "fmt"
+
+ "github.com/spf13/cobra"
+)
// Version information set by link flags during build. We fall back to these sane
// default values when not provided
@@ -18,9 +22,28 @@ func (v Version) String() string {
return fmt.Sprintf("validator version %v", v.Version)
}
+// SetVersion set the version
+func SetVersion(v string) {
+ version = v
+}
+
// GetVersion returns the version information
func GetVersion() Version {
return Version{
Version: version,
}
}
+
+func init() {
+ rootCmd.AddCommand(versionCmd)
+}
+
+// versionCmd command configuration and setup
+var versionCmd = &cobra.Command{
+ Use: "version",
+ Short: "Version prints the release version of validator",
+ Long: ``,
+ Run: func(cmd *cobra.Command, args []string) {
+ fmt.Println(GetVersion())
+ },
+}
diff --git a/cmd/validator/commands/version_test.go b/cmd/validator/commands/version_test.go
new file mode 100644
index 00000000..ad8814a9
--- /dev/null
+++ b/cmd/validator/commands/version_test.go
@@ -0,0 +1,33 @@
+package cmd
+
+import (
+ "testing"
+
+ cmd "github.com/Boeing/config-file-validator/cmd/validator"
+ "github.com/spf13/cobra"
+)
+
+func TestFlagVersion(t *testing.T) {
+ var exitStatus int
+ expectedExit := 0
+ root := &cobra.Command{
+ Use: "root",
+ Run: func(c *cobra.Command, args []string) {
+ exitStatus = cmd.ExecRoot(c, args)
+ }}
+
+ SetVersion("testing")
+ root.AddCommand(versionCmd)
+
+ args := []string{"version"}
+
+ _, err := ExecuteTestHelper(t, root, args...)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if expectedExit != exitStatus {
+ t.Errorf("Wrong exit code, expected: %v, got: %v", expectedExit, exitStatus)
+ }
+
+}
diff --git a/cmd/validator/validator.go b/cmd/validator/validator.go
index 63fceebc..b0e671bf 100644
--- a/cmd/validator/validator.go
+++ b/cmd/validator/validator.go
@@ -5,64 +5,83 @@ validates them using the go package for each configuration type.
Currently Apple PList XML, CSV, HCL, HOCON, INI, JSON, Properties, TOML, XML, and YAML.
configuration file types are supported.
-Usage: validator [OPTIONS] [...]
-
-positional arguments:
- search_path: The search path on the filesystem for configuration files. Defaults to the current working directory if no search_path provided. Multiple search paths can be declared separated by a space.
-
-optional flags:
- -depth int
- Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal
- -exclude-dirs string
- Subdirectories to exclude when searching for configuration files
- -exclude-file-types string
- A comma separated list of file types to ignore
- -output
- Destination of a file to outputting results
- -reporter string
- Format of the printed report. Options are standard and json (default "standard")
- -version
- Version prints the release version of validator
+Cross Platform tool to validate configuration files
+
+Usage:
+ validator [flags]
+ validator [command]
+
+Available Commands:
+ completion Generate the autocompletion script for the specified shell
+ help Help about any command
+ version Version prints the release version of validator
+
+Flags:
+ --depth int Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal.
+ --exclude-dirs string Subdirectories to exclude when searching for configuration files
+ --exclude-file-types string A comma separated list of file types to ignore
+ --groupby string Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
+ -h, --help help for validator
+ --output string Destination to a file to output results
+ --quiet If quiet flag is set. It doesn't print any output to stdout.
+ --reporter string Format of the printed report. Options are standard and json (default "standard")
+
+Use "validator [command] --help" for more information about a command.
*/
-package main
+package cmd
import (
"errors"
- "flag"
"fmt"
"log"
- "os"
"slices"
"strings"
- configfilevalidator "github.com/Boeing/config-file-validator"
"github.com/Boeing/config-file-validator/pkg/cli"
"github.com/Boeing/config-file-validator/pkg/finder"
"github.com/Boeing/config-file-validator/pkg/reporter"
+ "github.com/spf13/cobra"
)
-type validatorConfig struct {
- searchPaths []string
- excludeDirs *string
- excludeFileTypes *string
- reportType *string
- depth *int
- versionQuery *bool
- output *string
- groupOutput *string
- quiet *bool
+// ValidatorConfig holds all flag possible to be setted
+type ValidatorConfig struct {
+ SearchPaths []string
+ Depth int
+ ExcludeDirs string
+ ExcludeFileTypes string
+ Output string
+ ReportType string
+ GroupOutput string
+ Quiet bool
}
-// Custom Usage function to cover
-func validatorUsage() {
- fmt.Printf("Usage: validator [OPTIONS] [...]\n\n")
- fmt.Printf("positional arguments:\n")
- fmt.Printf(
- " search_path: The search path on the filesystem for configuration files. " +
- "Defaults to the current working directory if no search_path provided\n\n")
- fmt.Printf("optional flags:\n")
- flag.PrintDefaults()
+var Flags ValidatorConfig
+
+// isFlagSet verifies if a given flag has been set or not
+func isFlagSet(flagName string, cmd *cobra.Command) bool {
+ return cmd.Flags().Lookup(flagName).Changed
+}
+
+// CleanString takes a command string and a split string
+// and returns a cleaned string
+func CleanString(str string) string {
+ str = strings.ToLower(str)
+ str = strings.TrimSpace(str)
+ return str
+}
+
+// Return the reporter associated with the
+// reportType string
+func getReporter(reportType, outputDest string) reporter.Reporter {
+ switch reportType {
+ case "junit":
+ return reporter.NewJunitReporter(outputDest)
+ case "json":
+ return reporter.NewJSONReporter(outputDest)
+ default:
+ return reporter.StdoutReporter{}
+ }
}
// Parses, validates, and returns the flags
@@ -70,157 +89,116 @@ func validatorUsage() {
// If a required parameter is missing the help
// output will be displayed and the function
// will return with exit = 1
-func getFlags() (validatorConfig, error) {
- flag.Usage = validatorUsage
- depthPtr := flag.Int("depth", 0, "Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal")
- excludeDirsPtr := flag.String("exclude-dirs", "", "Subdirectories to exclude when searching for configuration files")
- excludeFileTypesPtr := flag.String("exclude-file-types", "", "A comma separated list of file types to ignore")
- outputPtr := flag.String("output", "", "Destination to a file to output results")
- reportTypePtr := flag.String("reporter", "standard", "Format of the printed report. Options are standard and json")
- versionPtr := flag.Bool("version", false, "Version prints the release version of validator")
- groupOutputPtr := flag.String("groupby", "", "Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports")
- quietPrt := flag.Bool("quiet", false, "If quiet flag is set. It doesn't print any output to stdout.")
- flag.Parse()
+func getFlags(cmd *cobra.Command, args []string) (ValidatorConfig, error) {
+ depth := Flags.Depth
+ excludeDirs := Flags.ExcludeDirs
+ excludeFileTypes := Flags.ExcludeFileTypes
+ output := Flags.Output
+ reportType := Flags.ReportType
+ groupby := Flags.GroupOutput
+ quiet := Flags.Quiet
searchPaths := make([]string, 0)
- // If search path arg is empty, set it to the cwd
- // if not, set it to the arg. Supports n number of
+ // If search path arg is empty, default is cwd (".")
+ // if not, set it to the arg. Supports N number of
// paths
- if flag.NArg() == 0 {
+ if len(args) == 0 {
searchPaths = append(searchPaths, ".")
} else {
- searchPaths = append(searchPaths, flag.Args()...)
+ searchPaths = append(searchPaths, args...)
}
- if *reportTypePtr != "standard" && *reportTypePtr != "json" && *reportTypePtr != "junit" {
+ if reportType != "standard" && reportType != "json" && reportType != "junit" {
fmt.Println("Wrong parameter value for reporter, only supports standard, json or junit")
- flag.Usage()
- return validatorConfig{}, errors.New("Wrong parameter value for reporter, only supports standard, json or junit")
+ _ = cmd.Usage()
+ return ValidatorConfig{}, errors.New("Wrong parameter value for reporter, only supports standard, json or junit")
}
- if *reportTypePtr == "junit" && *groupOutputPtr != "" {
+ if reportType == "junit" && groupby != "" {
fmt.Println("Wrong parameter value for reporter, groupby is not supported for JUnit reports")
- flag.Usage()
- return validatorConfig{}, errors.New("Wrong parameter value for reporter, groupby is not supported for JUnit reports")
+ _ = cmd.Usage()
+ return ValidatorConfig{}, errors.New("Wrong parameter value for reporter, groupby is not supported for JUnit reports")
}
- if depthPtr != nil && isFlagSet("depth") && *depthPtr < 0 {
+ if isFlagSet("depth", cmd) && depth < 0 {
fmt.Println("Wrong parameter value for depth, value cannot be negative.")
- flag.Usage()
- return validatorConfig{}, errors.New("Wrong parameter value for depth, value cannot be negative")
+ _ = cmd.Usage()
+ return ValidatorConfig{}, errors.New("Wrong parameter value for depth, value cannot be negative")
}
- groupByCleanString := cleanString("groupby")
- groupByUserInput := strings.Split(groupByCleanString, ",")
- groupByAllowedValues := []string{"filetype", "directory", "pass-fail"}
- seenValues := make(map[string]bool)
+ if groupby != "" {
+ groupByCleanString := CleanString(groupby)
+ groupByUserInput := strings.Split(groupByCleanString, ",")
+ groupByAllowedValues := []string{"filetype", "directory", "pass-fail"}
+ seenValues := make(map[string]bool)
- // Check that the groupby values are valid and not duplicates
- if groupOutputPtr != nil && isFlagSet("groupby") {
+ // Check that the groupby values are valid and not duplicates
for _, groupBy := range groupByUserInput {
if !slices.Contains(groupByAllowedValues, groupBy) {
fmt.Println("Wrong parameter value for groupby, only supports filetype, directory, pass-fail")
- flag.Usage()
- return validatorConfig{}, errors.New("Wrong parameter value for groupby, only supports filetype, directory, pass-fail")
+ _ = cmd.Usage()
+ return ValidatorConfig{}, errors.New(
+ "Wrong parameter value for groupby, only supports filetype, directory, pass-fail",
+ )
}
if _, ok := seenValues[groupBy]; ok {
fmt.Println("Wrong parameter value for groupby, duplicate values are not allowed")
- flag.Usage()
- return validatorConfig{}, errors.New("Wrong parameter value for groupby, duplicate values are not allowed")
+ _ = cmd.Usage()
+ return ValidatorConfig{}, errors.New("Wrong parameter value for groupby, duplicate values are not allowed")
}
seenValues[groupBy] = true
}
}
- config := validatorConfig{
- searchPaths,
- excludeDirsPtr,
- excludeFileTypesPtr,
- reportTypePtr,
- depthPtr,
- versionPtr,
- outputPtr,
- groupOutputPtr,
- quietPrt,
+ config := ValidatorConfig{
+ SearchPaths: searchPaths,
+ ExcludeDirs: excludeDirs,
+ ExcludeFileTypes: excludeFileTypes,
+ ReportType: reportType,
+ Depth: depth,
+ Output: output,
+ GroupOutput: groupby,
+ Quiet: quiet,
}
return config, nil
}
-// isFlagSet verifies if a given flag has been set or not
-func isFlagSet(flagName string) bool {
- var isSet bool
-
- flag.Visit(func(f *flag.Flag) {
- if f.Name == flagName {
- isSet = true
- }
- })
-
- return isSet
-}
-
-// Return the reporter associated with the
-// reportType string
-func getReporter(reportType, outputDest *string) reporter.Reporter {
- switch *reportType {
- case "junit":
- return reporter.NewJunitReporter(*outputDest)
- case "json":
- return reporter.NewJSONReporter(*outputDest)
- default:
- return reporter.StdoutReporter{}
- }
-}
-
-// cleanString takes a command string and a split string
-// and returns a cleaned string
-func cleanString(command string) string {
- cleanedString := flag.Lookup(command).Value.String()
- cleanedString = strings.ToLower(cleanedString)
- cleanedString = strings.TrimSpace(cleanedString)
-
- return cleanedString
-}
-
-func mainInit() int {
- validatorConfig, err := getFlags()
+// ExecRoot control all the flow of the program and call cli.Run() that process everything.
+func ExecRoot(cmd *cobra.Command, args []string) int {
+ validatorConfig, err := getFlags(cmd, args)
if err != nil {
return 1
}
- if *validatorConfig.versionQuery {
- fmt.Println(configfilevalidator.GetVersion())
- return 0
- }
-
// since the exclude dirs are a comma separated string
// it needs to be split into a slice of strings
- excludeDirs := strings.Split(*validatorConfig.excludeDirs, ",")
- choosenReporter := getReporter(validatorConfig.reportType, validatorConfig.output)
- excludeFileTypes := strings.Split(*validatorConfig.excludeFileTypes, ",")
- groupOutput := strings.Split(*validatorConfig.groupOutput, ",")
+ excludeDirs := strings.Split(validatorConfig.ExcludeDirs, ",")
+ excludeFileTypes := strings.Split(validatorConfig.ExcludeFileTypes, ",")
+
fsOpts := []finder.FSFinderOptions{
- finder.WithPathRoots(validatorConfig.searchPaths...),
+ finder.WithPathRoots(validatorConfig.SearchPaths...),
finder.WithExcludeDirs(excludeDirs),
finder.WithExcludeFileTypes(excludeFileTypes),
}
- quiet := *validatorConfig.quiet
- if validatorConfig.depth != nil && isFlagSet("depth") {
- fsOpts = append(fsOpts, finder.WithDepth(*validatorConfig.depth))
+ if isFlagSet("depth", cmd) {
+ fsOpts = append(fsOpts, finder.WithDepth(validatorConfig.Depth))
}
// Initialize a file system finder
fileSystemFinder := finder.FileSystemFinderInit(fsOpts...)
+ choosenReporter := getReporter(validatorConfig.ReportType, validatorConfig.Output)
+ groupby := strings.Split(validatorConfig.GroupOutput, ",")
+
// Initialize the CLI
c := cli.Init(
cli.WithReporter(choosenReporter),
cli.WithFinder(fileSystemFinder),
- cli.WithGroupOutput(groupOutput),
- cli.WithQuiet(quiet),
+ cli.WithGroupOutput(groupby),
+ cli.WithQuiet(validatorConfig.Quiet),
)
// Run the config file validation
@@ -231,7 +209,3 @@ func mainInit() int {
return exitStatus
}
-
-func main() {
- os.Exit(mainInit())
-}
diff --git a/cmd/validator/validator_test.go b/cmd/validator/validator_test.go
deleted file mode 100644
index bcd9c03b..00000000
--- a/cmd/validator/validator_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package main
-
-import (
- "flag"
- "fmt"
- "os"
- "testing"
-)
-
-func Test_flags(t *testing.T) {
- // We manipuate the Args to set them up for the testcases
- // After this test we restore the initial args
- oldArgs := os.Args
- defer func() { os.Args = oldArgs }()
- cases := []struct {
- Name string
- Args []string
- ExpectedExit int
- }{
- {"blank", []string{}, 0},
- {"negative depth set", []string{"-depth=-1", "."}, 1},
- {"depth set", []string{"-depth=1", "."}, 0},
- {"flags set, wrong reporter", []string{"--exclude-dirs=subdir", "--reporter=wrong", "."}, 1},
- {"flags set, json reporter", []string{"--exclude-dirs=subdir", "--reporter=json", "."}, 0},
- {"flags set, junit reported", []string{"--exclude-dirs=subdir", "--reporter=junit", "."}, 0},
- {"bad path", []string{"/path/does/not/exit"}, 1},
- {"exclude file types set", []string{"--exclude-file-types=json", "."}, 0},
- {"multiple paths", []string{"../../test/fixtures/subdir/good.json", "../../test/fixtures/good.json"}, 0},
- {"version", []string{"--version"}, 0},
- {"output set", []string{"--output=../../test/output", "--reporter=json", "."}, 0},
- {"empty string output set", []string{"--output", "", "--reporter", "json", "."}, 0},
- {"wrong output set", []string{"--output", "/path/not/exist", "--reporter", "json", "."}, 1},
- {"incorrect group", []string{"-groupby=badgroup", "."}, 1},
- {"correct group", []string{"-groupby=directory", "."}, 0},
- {"grouped junit", []string{"-groupby=directory", "--reporter=junit", "."}, 1},
- {"groupby duplicate", []string{"--groupby=directory,directory", "."}, 1},
- {"quiet flag", []string{"--quiet=true", "."}, 0},
- }
- for _, tc := range cases {
- // this call is required because otherwise flags panics,
- // if args are set between flag.Parse call
- fmt.Printf("Testing args: %v = %v\n", tc.Name, tc.Args)
- flag.CommandLine = flag.NewFlagSet(tc.Name, flag.ExitOnError)
- // we need a value to set Args[0] to cause flag begins parsing at Args[1]
- os.Args = append([]string{tc.Name}, tc.Args...)
- actualExit := mainInit()
- if tc.ExpectedExit != actualExit {
- t.Errorf("Wrong exit code, expected: %v, got: %v", tc.ExpectedExit, actualExit)
- }
- }
-}
diff --git a/go.mod b/go.mod
index 1a90e610..d59d0d44 100644
--- a/go.mod
+++ b/go.mod
@@ -5,9 +5,11 @@ go 1.21
require (
github.com/fatih/color v1.13.0
github.com/gurkankaymak/hocon v1.2.18
+ github.com/hashicorp/go-envparse v0.1.0
github.com/hashicorp/hcl/v2 v2.18.1
github.com/magiconair/properties v1.8.7
github.com/pelletier/go-toml/v2 v2.0.6
+ github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.1
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
@@ -20,13 +22,13 @@ require (
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/go-cmp v0.5.8 // indirect
- github.com/hashicorp/go-envparse v0.1.0 // indirect
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
github.com/zclconf/go-cty v1.13.0 // indirect
- golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.11.0 // indirect
)
diff --git a/go.sum b/go.sum
index 5984a6d1..37b06d7a 100644
--- a/go.sum
+++ b/go.sum
@@ -4,6 +4,7 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -19,6 +20,8 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm
github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc=
github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo=
github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -39,6 +42,11 @@ github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvI
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -48,8 +56,6 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0=
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
-golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
-golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/img/gb-filetype-and-pass-fail.png b/img/gb-filetype-and-pass-fail.png
deleted file mode 100644
index 3a30c2ae..00000000
Binary files a/img/gb-filetype-and-pass-fail.png and /dev/null differ
diff --git a/img/gb-filetype.png b/img/gb-filetype.png
deleted file mode 100644
index a89f93eb..00000000
Binary files a/img/gb-filetype.png and /dev/null differ
diff --git a/index.md b/index.md
index b1be0fe1..6453599d 100644
--- a/index.md
+++ b/index.md
@@ -111,28 +111,28 @@ go install github.com/Boeing/config-file-validator/cmd/validator@v1.6.0
## Usage
```
-Usage: validator [OPTIONS] [...]
-
-positional arguments:
- search_path: The search path on the filesystem for configuration files. Defaults to the current working directory if no search_path provided
-
-optional flags:
- -depth int
- Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal
- -exclude-dirs string
- Subdirectories to exclude when searching for configuration files
- -exclude-file-types string
- A comma separated list of file types to ignore
- -groupby string
- Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
- -output string
- Destination to a file to output results
- -quiet
- If quiet flag is set. It doesn't print any output to stdout.
- -reporter string
- Format of the printed report. Options are standard and json (default "standard")
- -version
- Version prints the release version of validator
+Cross Platform tool to validate configuration files
+
+Usage:
+ validator [flags]
+ validator [command]
+
+Available Commands:
+ completion Generate the autocompletion script for the specified shell
+ help Help about any command
+ version Version prints the release version of validator
+
+Flags:
+ --depth int Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal.
+ --exclude-dirs string Subdirectories to exclude when searching for configuration files
+ --exclude-file-types string A comma separated list of file types to ignore
+ --groupby string Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
+ -h, --help help for validator
+ --output string Destination to a file to output results
+ --quiet If quiet flag is set. It doesn't print any output to stdout.
+ --reporter string Format of the printed report. Options are standard and json (default "standard")
+
+Use "validator [command] --help" for more information about a command.
```
### Examples
diff --git a/main.go b/main.go
new file mode 100644
index 00000000..1a357b11
--- /dev/null
+++ b/main.go
@@ -0,0 +1,7 @@
+package main
+
+import cmd "github.com/Boeing/config-file-validator/cmd/validator/commands"
+
+func main() {
+ cmd.Execute()
+}
diff --git a/pkg/finder/finder_test.go b/pkg/finder/finder_test.go
index 4b5b8242..6e1fd206 100644
--- a/pkg/finder/finder_test.go
+++ b/pkg/finder/finder_test.go
@@ -204,7 +204,7 @@ func Test_FileSystemFinderAbsPath(t *testing.T) {
}
}
-func Test_FileSystemFinderUpperCaseExtension(t *testing.T) {
+func Test_FileSystemFinderUpperCaseExtention(t *testing.T) {
fsFinder := FileSystemFinderInit(
WithPathRoots("../../test/fixtures/uppercase-extension"),
)
@@ -220,7 +220,7 @@ func Test_FileSystemFinderUpperCaseExtension(t *testing.T) {
}
}
-func Test_FileSystemFinderMixedCaseExtension(t *testing.T) {
+func Test_FileSystemFinderMixedCaseExtention(t *testing.T) {
fsFinder := FileSystemFinderInit(
WithPathRoots("../../test/fixtures/mixedcase-extension"),
)
diff --git a/pkg/validator/validator_test.go b/pkg/validator/validator_test.go
index ac07aca4..f90a9e45 100644
--- a/pkg/validator/validator_test.go
+++ b/pkg/validator/validator_test.go
@@ -64,8 +64,6 @@ var testData = []struct {
{"invalidPlist", invalidPlistBytes, false, PlistValidator{}},
{"validHocon", []byte(`test = [1, 2, 3]`), true, HoconValidator{}},
{"invalidHocon", []byte(`test = [1, 2,, 3]`), false, HoconValidator{}},
- {"validEnv", []byte("KEY=VALUE"), true, EnvValidator{}},
- {"invalidEnv", []byte("=TEST"), false, EnvValidator{}},
}
func Test_ValidationInput(t *testing.T) {
diff --git a/test/fixtures/good.env b/test/fixtures/good.env
deleted file mode 100644
index 4655ae15..00000000
--- a/test/fixtures/good.env
+++ /dev/null
@@ -1 +0,0 @@
-TEST=True
diff --git a/test/fixtures/subdir2/bad.env b/test/fixtures/subdir2/bad.env
deleted file mode 100644
index 6c00b663..00000000
--- a/test/fixtures/subdir2/bad.env
+++ /dev/null
@@ -1,2 +0,0 @@
-TEST=True
-DEMO="\a"