diff --git a/cmd/policygen/config.go b/cmd/policygen/config.go index 398f05a..1c3fc5b 100644 --- a/cmd/policygen/config.go +++ b/cmd/policygen/config.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" "fmt" - "github.com/go-playground/validator/v10" "github.com/goccy/go-yaml" "log" "net" @@ -95,8 +94,13 @@ func (c *Config) Update(config *Config) { } func (c Config) ValidateSchema() error { - validate := validator.New(validator.WithRequiredStructEnabled()) - return validate.Struct(c) + + validator, err := NewValidator() + if err != nil { + return err + } + err = validator.ValidateStruct(c) + return err } func (c Config) Validate() error { diff --git a/cmd/policygen/validator.go b/cmd/policygen/validator.go new file mode 100644 index 0000000..1818c2e --- /dev/null +++ b/cmd/policygen/validator.go @@ -0,0 +1,82 @@ +package main + +import ( + "errors" + "fmt" + "github.com/go-playground/locales/en" + ut "github.com/go-playground/universal-translator" + "github.com/go-playground/validator/v10" + en_translations "github.com/go-playground/validator/v10/translations/en" +) + +type Validator struct { + validate *validator.Validate + trans ut.Translator +} + +type Translation struct { + format string + params func(fe validator.FieldError) []any +} + +var translations = map[string]Translation{ + "oneof": { + "{0} must be one of [{1}], got '{2}'", + func(fe validator.FieldError) []any { + return []any{fe.Field(), fe.Param(), fe.Value()} + }, + }, +} + +func NewValidator() (*Validator, error) { + validate := validator.New(validator.WithRequiredStructEnabled()) + language := en.New() + translator := ut.New(language, language) + trans, ok := translator.GetTranslator("en") + if !ok { + return nil, fmt.Errorf("Could not find translator to print error meesage") + } + en_translations.RegisterDefaultTranslations(validate, trans) + + for validation, translation := range translations { + validate.RegisterTranslation(validation, trans, + func(ut ut.Translator) error { + return ut.Add(validation, translation.format, true) + }, + func(ut ut.Translator, fe validator.FieldError) string { + params := translation.params(fe) + stringParams := make([]string, len(params)) + for i, param := range params { + stringParams[i] = fmt.Sprintf("%s", param) + } + t, _ := ut.T(validation, stringParams...) + return t + }) + } + + return &Validator{ + validate: validate, + trans: trans, + }, nil +} + +func (v Validator) ValidateStruct(s interface{}) error { + err := v.validate.Struct(s) + return v.Translate(err) +} + +func (v Validator) Translate(err error) error { + if err == nil { + return err + } + errs, ok := err.(validator.ValidationErrors) + if !ok { + return err + } + + errorList := make([]error, 0) + for _, e := range errs { + errorList = append(errorList, fmt.Errorf("%s", e.Translate(v.trans))) + } + return errors.Join(errorList...) +} diff --git a/example/config.yaml b/example/config.yaml index 757dc49..02e8237 100644 --- a/example/config.yaml +++ b/example/config.yaml @@ -10,13 +10,14 @@ networks: - 192.168.0.0/16 ports: - port: 2303 + protocol: UDP namespaces: - name: wamblee-org #open: true capabilities: - - linkerdd + - linkerd - dns applications: - name: nexus-server