Skip to content

Commit

Permalink
feat: add validator (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
tao12345666333 authored Aug 23, 2023
1 parent 458e091 commit 524b2a0
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
7 changes: 7 additions & 0 deletions cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/fatih/color"
"github.com/spf13/cobra"

"github.com/api7/adc/internal/pkg/validator"
"github.com/api7/adc/pkg/api/apisix/types"
"github.com/api7/adc/pkg/common"
)
Expand Down Expand Up @@ -50,5 +51,11 @@ func newValidateCmd() *cobra.Command {

// validateContent validates the content of the configuration file
func validateContent(c *types.Configuration) error {
v, err := validator.NewValidator(c)
if err != nil {
color.Red("Failed to create validator: %v", err)
return err
}
v.Validate()
return nil
}
106 changes: 106 additions & 0 deletions internal/pkg/validator/validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package validator

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"reflect"

"github.com/api7/adc/pkg/api/apisix/types"
"github.com/api7/adc/pkg/data"
)

type Validator struct {
localConfig *types.Configuration

evenChan *data.Event
}

func NewValidator(local *types.Configuration) (*Validator, error) {
return &Validator{
localConfig: local,
}, nil
}

type ErrorsWrapper struct {
Errors []error
}

func (v ErrorsWrapper) Error() string {
var errStr string
for _, e := range v.Errors {
errStr += e.Error()
if !errors.Is(e, v.Errors[len(v.Errors)-1]) {
errStr += "\n"
}
}
return errStr
}

func getResourceNameOrID(resource interface{}) string {
value := reflect.ValueOf(resource)
value = reflect.Indirect(value)
nameOrID := value.FieldByName("Name")
if !nameOrID.IsValid() {
nameOrID = value.FieldByName("ID")
}
return nameOrID.String()
}

type RespData struct {
ErrMsg string `json: "error_msg"`
}

func (v *Validator) validateResource(resourceType string, resource interface{}) error {
nameOrID := getResourceNameOrID(resource)
errWrap := "validate resource '%s (%s)': %s"
endpoint := fmt.Sprintf("/apisix/admin/schema/validate/%s", resourceType)
httpClient := &http.Client{}
jsonData, err := json.Marshal(resource)
if err != nil {
return fmt.Errorf(errWrap, resourceType, nameOrID, err)
}

req, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewBuffer(jsonData))
if err != nil {
return fmt.Errorf(errWrap, resourceType, nameOrID, err)
}
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf(errWrap, resourceType, nameOrID, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
respData := &RespData{}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf(errWrap, resourceType, nameOrID, err)
}
err = json.Unmarshal(body, respData)
if err != nil {
return fmt.Errorf(errWrap, resourceType, nameOrID, err)
}
if resp != nil {
return fmt.Errorf(errWrap, resourceType, nameOrID, respData.ErrMsg)
}
return fmt.Errorf(errWrap, resourceType, nameOrID, "invalid")
}
return nil
}

func (v *Validator) Validate() []error {
allErr := []error{}

for _, service := range v.localConfig.Services {
service := service
err := v.validateResource("service", service)
if err != nil {
allErr = append(allErr, err)
}
}

return allErr
}

0 comments on commit 524b2a0

Please sign in to comment.