Skip to content

Commit

Permalink
chore: refactor commands to remove duplication, add -output option to…
Browse files Browse the repository at this point in the history
… validate command
  • Loading branch information
omissis committed Aug 16, 2022
1 parent 4d61984 commit 1080cd5
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 144 deletions.
90 changes: 90 additions & 0 deletions cmd/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cmd

import (
"log"
"os"
"path/filepath"
"strings"

"github.com/mitchellh/cli"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
)

// configs contains a list of files where ruleset are specified
type configFiles []string

func (i *configFiles) String() string {
return strings.Join(*i, ",")
}

func (i *configFiles) Set(value string) error {
*i = append(*i, value)
return nil
}

func VerifyFactory() (cli.Command, error) {
return &verifyCommand{}, nil
}

func getWd() string {
cwd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

return cwd
}

func listConfigFiles(cfs []string) []string {
configFiles := make([]string, 0)

for _, cf := range cfs {
fileInfo, err := os.Stat(cf)
if err != nil {
log.Fatal(err)
}

if !fileInfo.IsDir() {
configFiles = append(configFiles, cf)
continue
}

if err := filepath.Walk(cf, visitConfigFolder(&configFiles)); err != nil {
log.Fatal(err)
}
}

slices.Sort(configFiles)

return slices.Compact(configFiles)
}

func visitConfigFolder(files *[]string) filepath.WalkFunc {
return func(path string, file os.FileInfo, err error) error {
if err != nil {
return err
}

if !file.IsDir() && filepath.Ext(path) == ".yaml" {
*files = append(*files, path)
}

return nil
}
}

func loadConfig[T any](file string) T {
var conf T

configData, err := os.ReadFile(file)
if err != nil {
log.Fatal(err)
}

if err := yaml.Unmarshal(configData, &conf); err != nil {
log.Fatal(err)
}

return conf
}
92 changes: 27 additions & 65 deletions cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,55 +3,48 @@ package cmd
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"goarkitect/internal/schema/santhosh"
"log"
"os"
"path/filepath"

"github.com/mitchellh/cli"
"github.com/santhosh-tekuri/jsonschema"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
)

func ValidateFactory() (cli.Command, error) {
return &validateCommand{}, nil
}

type validateCommand struct {
configFiles configFiles
output string
}

func (vc *validateCommand) Help() string {
return "TBD"
}

func (vc *validateCommand) Run(args []string) int {
basePath := vc.getCwd()
basePath := getWd()

ruleset := vc.parseArgs(basePath, args)
vc.parseFlags()

schema := vc.loadSchema(basePath)

for _, subject := range ruleset {
// TODO: print in debug mode
// log.Printf("validating %s", subject)
for _, configFile := range vc.configFiles {
fmt.Printf("CONFIG FILE %s\n", configFile)

configPath := filepath.Join(basePath, subject)

configData, err := os.ReadFile(configPath)
if err != nil {
log.Fatal(err)
}

var conf interface{}
if err := yaml.Unmarshal(configData, &conf); err != nil {
log.Fatal(err)
}
conf := loadConfig[any](configFile)

if err := schema.ValidateInterface(conf); err != nil {
vc.logValidationError(err, subject, conf)
vc.logValidationError(err, conf)

log.Fatal(err)
} else {
fmt.Println("ok")
}
}

Expand All @@ -62,55 +55,25 @@ func (vc *validateCommand) Synopsis() string {
return "Validate the configuration file(s)"
}

func (vc *validateCommand) getCwd() string {
basePath, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

return basePath
}
// parseFlags returns the list of config files, the output format and the base path
func (vc *validateCommand) parseFlags() {
out := ""

func (vc *validateCommand) parseArgs(basePath string, args []string) []string {
if len(args) < 1 {
return []string{".goarkitect.yaml"}
}
flagSet := flag.NewFlagSet("validate", flag.ExitOnError)

ruleset := make([]string, 0)
flagSet.StringVar(&out, "output", "text", "format of the output")

for _, arg := range args {
fileInfo, err := os.Stat(arg)
if err != nil {
log.Fatal(err)
}

if !fileInfo.IsDir() {
ruleset = append(ruleset, arg)
continue
}

if err := filepath.Walk(arg, vc.visitFolder(&ruleset)); err != nil {
log.Fatal(err)
}
if err := flagSet.Parse(os.Args[2:]); err != nil {
log.Fatal(err)
}

slices.Sort(ruleset)

return slices.Compact(ruleset)
}

func (e *validateCommand) visitFolder(files *[]string) filepath.WalkFunc {
return func(path string, file os.FileInfo, err error) error {
if err != nil {
return err
}

if !file.IsDir() {
*files = append(*files, path)
}

return nil
cfs := flagSet.Args()
if len(cfs) < 1 {
cfs = []string{".goarkitect.yaml"}
}

vc.output = out
vc.configFiles = listConfigFiles(cfs)
}

func (vc *validateCommand) loadSchema(basePath string) *jsonschema.Schema {
Expand All @@ -134,7 +97,7 @@ func (vc *validateCommand) loadSchema(basePath string) *jsonschema.Schema {
return schema
}

func (vc *validateCommand) logValidationError(err error, subject string, conf any) {
func (vc *validateCommand) logValidationError(err error, conf any) {
ptrPaths := santhosh.GetPtrPaths(err.(*jsonschema.ValidationError))
for _, path := range ptrPaths {
value, err := json.Marshal(santhosh.GetValueAtPath(conf, path))
Expand All @@ -143,8 +106,7 @@ func (vc *validateCommand) logValidationError(err error, subject string, conf an
}

log.Printf(
"file '%s': path '%s' contains an invalid configuration value: %+v\n",
subject,
"path '%s' contains an invalid configuration value: %+v\n",
santhosh.JoinPtrPath(path),
string(value),
)
Expand Down
82 changes: 3 additions & 79 deletions cmd/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,8 @@ import (
"log"
"os"
"path/filepath"
"strings"

"github.com/mitchellh/cli"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
)

// configs contains a list of files where ruleset are specified
type configFiles []string

func (i *configFiles) String() string {
return strings.Join(*i, ",")
}

func (i *configFiles) Set(value string) error {
*i = append(*i, value)
return nil
}

func VerifyFactory() (cli.Command, error) {
return &verifyCommand{}, nil
}

type verifyCommand struct {
configFiles configFiles
output string
Expand All @@ -44,16 +23,8 @@ func (vc *verifyCommand) Run(args []string) int {

for _, configFile := range vc.configFiles {
fmt.Printf("CONFIG FILE %s\n", configFile)
// TODO: recognize if config is relative or absolute, then adjust configFile accordingly
configData, err := os.ReadFile(configFile)
if err != nil {
log.Fatal(err)
}

var conf config.Root
if err := yaml.Unmarshal(configData, &conf); err != nil {
log.Fatal(err)
}
conf := loadConfig[config.Root](configFile)

results := config.Execute(conf)

Expand All @@ -67,15 +38,6 @@ func (vc *verifyCommand) Synopsis() string {
return "Verify the ruleset against a project"
}

func (vc *verifyCommand) getCwd() string {
cwd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

return cwd
}

// parseFlags returns the list of config files, the output format and the base path
func (vc *verifyCommand) parseFlags() {
cfs := configFiles{}
Expand All @@ -91,49 +53,11 @@ func (vc *verifyCommand) parseFlags() {
}

if len(cfs) < 1 {
cfs = []string{filepath.Join(vc.getCwd(), ".goarkitect.yaml")}
cfs = []string{filepath.Join(getWd(), ".goarkitect.yaml")}
}

vc.output = out
vc.configFiles = vc.listConfigFiles(cfs)
}

func (vc *verifyCommand) listConfigFiles(cfs []string) []string {
configFiles := make([]string, 0)

for _, cf := range cfs {
fileInfo, err := os.Stat(cf)
if err != nil {
log.Fatal(err)
}

if !fileInfo.IsDir() {
configFiles = append(configFiles, cf)
continue
}

if err := filepath.Walk(cf, vc.visitConfigFolder(&configFiles)); err != nil {
log.Fatal(err)
}
}

slices.Sort(configFiles)

return slices.Compact(configFiles)
}

func (vc *verifyCommand) visitConfigFolder(files *[]string) filepath.WalkFunc {
return func(path string, file os.FileInfo, err error) error {
if err != nil {
return err
}

if !file.IsDir() && filepath.Ext(path) == ".yaml" {
*files = append(*files, path)
}

return nil
}
vc.configFiles = listConfigFiles(cfs)
}

func (vc *verifyCommand) printResults(results []config.RuleExecutionResult) {
Expand Down

0 comments on commit 1080cd5

Please sign in to comment.