This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new ebf5026  [SCD-2133] add scene id / add custome err (#826)
ebf5026 is described below

commit ebf5026de08fd24203389e6083b516003b9a4ffc
Author: GuoYL <[email protected]>
AuthorDate: Mon Jan 11 21:06:51 2021 +0800

    [SCD-2133] add scene id / add custome err (#826)
    
    * [SCD-2133] add scene id / add custome err
    
    (cherry picked from commit 952e2de3d2b48d17f9de13a05b6c5e9142eb0439)
    
    * [SCD-2133] modify as comment
---
 server/resource/v1/gov_resource.go        | 47 +++++++++++++++--------------
 server/service/gov/kie/kie_distributor.go | 49 +++++++++++++++++++++++++++++--
 server/service/gov/kie/validate.go        | 37 +++++++++++++++--------
 server/service/gov/mock/mock.go           | 10 +++++--
 4 files changed, 103 insertions(+), 40 deletions(-)

diff --git a/server/resource/v1/gov_resource.go 
b/server/resource/v1/gov_resource.go
index 81f1579..601ec3d 100644
--- a/server/resource/v1/gov_resource.go
+++ b/server/resource/v1/gov_resource.go
@@ -21,6 +21,8 @@ import (
        "io/ioutil"
        "net/http"
 
+       "github.com/apache/servicecomb-service-center/server/service/gov/kie"
+
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/server/rest/controller"
@@ -51,18 +53,18 @@ func (t *Governance) Create(w http.ResponseWriter, req 
*http.Request) {
                return
        }
        id, err := gov.Create(kind, project, body)
-       //todo: 错误处理抽函数
        if err != nil {
-               log.Error("create gov err", err)
-               w.WriteHeader(http.StatusBadRequest)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               if _, ok := err.(*kie.ErrIllegalItem); ok {
+                       log.Error("", err)
+                       controller.WriteError(w, discovery.ErrInvalidParams, 
err.Error())
+                       return
+               }
+               processError(w, err, "create gov data err")
                return
        }
        _, err = w.Write(id)
        if err != nil {
-               w.WriteHeader(http.StatusBadRequest)
-               log.Error("", err)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               processError(w, err, "")
                return
        }
        w.WriteHeader(http.StatusOK)
@@ -81,9 +83,12 @@ func (t *Governance) Put(w http.ResponseWriter, req 
*http.Request) {
        }
        err = gov.Update(id, kind, project, body)
        if err != nil {
-               log.Error("put gov err", err)
-               w.WriteHeader(http.StatusBadRequest)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               if _, ok := err.(*kie.ErrIllegalItem); ok {
+                       log.Error("", err)
+                       controller.WriteError(w, discovery.ErrInvalidParams, 
err.Error())
+                       return
+               }
+               processError(w, err, "put gov err")
                return
        }
        w.WriteHeader(http.StatusOK)
@@ -103,16 +108,12 @@ func (t *Governance) ListOrDisPlay(w http.ResponseWriter, 
req *http.Request) {
                body, err = gov.List(kind, project, app, environment)
        }
        if err != nil {
-               log.Error("list gov err", err)
-               w.WriteHeader(http.StatusBadRequest)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               processError(w, err, "list gov err")
                return
        }
        _, err = w.Write(body)
        if err != nil {
-               w.WriteHeader(http.StatusBadRequest)
-               log.Error("", err)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               processError(w, err, "")
                return
        }
        w.WriteHeader(http.StatusOK)
@@ -133,9 +134,7 @@ func (t *Governance) Get(w http.ResponseWriter, req 
*http.Request) {
        }
        _, err = w.Write(body)
        if err != nil {
-               w.WriteHeader(http.StatusBadRequest)
-               log.Error("", err)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               processError(w, err, "")
                return
        }
        w.WriteHeader(http.StatusOK)
@@ -148,14 +147,18 @@ func (t *Governance) Delete(w http.ResponseWriter, req 
*http.Request) {
        project := req.URL.Query().Get(ProjectKey)
        err := gov.Delete(id, project)
        if err != nil {
-               w.WriteHeader(http.StatusBadRequest)
-               log.Error("delete gov err", err)
-               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               processError(w, err, "delete gov err")
                return
        }
        w.WriteHeader(http.StatusOK)
 }
 
+func processError(w http.ResponseWriter, err error, msg string) {
+       w.WriteHeader(http.StatusBadRequest)
+       log.Error(msg, err)
+       controller.WriteError(w, discovery.ErrInternal, err.Error())
+}
+
 func (t *Governance) URLPatterns() []rest.Route {
        return []rest.Route{
                //servicecomb.marker.{name}
diff --git a/server/service/gov/kie/kie_distributor.go 
b/server/service/gov/kie/kie_distributor.go
index 0fc5bd0..6fb1335 100644
--- a/server/service/gov/kie/kie_distributor.go
+++ b/server/service/gov/kie/kie_distributor.go
@@ -5,7 +5,9 @@ import (
        "context"
        "encoding/json"
        "fmt"
+       "math/rand"
        "strings"
+       "time"
 
        "github.com/apache/servicecomb-service-center/pkg/log"
 
@@ -30,6 +32,7 @@ const (
        AppKey         = "app"
        EnvironmentKey = "environment"
        EnvAll         = "all"
+       BusinessPrefix = "scene-"
 )
 
 var PolicyNames = []string{"retry", "rateLimiting", "circuitBreaker", 
"bulkhead"}
@@ -42,8 +45,13 @@ func (d *Distributor) Create(kind, project string, spec 
[]byte) ([]byte, error)
        if err != nil {
                return nil, err
        }
+       if kind == MatchGroup {
+               err = d.generateID(project, p)
+               if err != nil {
+                       return nil, err
+               }
+       }
        log.Info(fmt.Sprintf("create %v", &p))
-       key := toSnake(kind) + "." + p.Name
        err = rule.Validate(kind, p.Spec)
        if err != nil {
                return nil, err
@@ -53,7 +61,7 @@ func (d *Distributor) Create(kind, project string, spec 
[]byte) ([]byte, error)
                return nil, err
        }
        kv := kie.KVRequest{
-               Key:       PREFIX + key,
+               Key:       PREFIX + toSnake(kind) + "." + p.Name,
                Value:     string(yamlByte),
                Status:    EnableStatus,
                ValueType: ValueType,
@@ -241,6 +249,43 @@ func (d *Distributor) listDataByKind(kind, project, app, 
env string) (*kie.KVRes
        return d.client.List(context.TODO(), ops...)
 }
 
+func (d *Distributor) generateID(project string, p *gov.Policy) error {
+       if p.Name != "" {
+               return nil
+       }
+       list, _, err := d.listDataByKind(MatchGroup, project, p.Selector.App, 
p.Selector.Environment)
+       if err != nil {
+               return err
+       }
+       var id string
+       for {
+               var repeat bool
+               id = getID()
+               for _, datum := range list.Data {
+                       if id == MatchGroup+datum.Key {
+                               repeat = true
+                               break
+                       }
+               }
+               if !repeat {
+                       break
+               }
+       }
+       p.Name = id
+       return nil
+}
+
+func getID() string {
+       str := "0123456789abcdefghijklmnopqrstuvwxyz"
+       b := []byte(str)
+       var result []byte
+       r := rand.New(rand.NewSource(time.Now().UnixNano()))
+       for i := 0; i < 4; i++ {
+               result = append(result, b[r.Intn(len(b))])
+       }
+       return BusinessPrefix + string(result)
+}
+
 func (d *Distributor) transform(kv *kie.KVDoc, kind string) (*gov.Policy, 
error) {
        goc := &gov.Policy{
                GovernancePolicy: &gov.GovernancePolicy{},
diff --git a/server/service/gov/kie/validate.go 
b/server/service/gov/kie/validate.go
index bafe794..659e04e 100644
--- a/server/service/gov/kie/validate.go
+++ b/server/service/gov/kie/validate.go
@@ -7,7 +7,18 @@ import (
 type Validator struct {
 }
 
-var methodSet map[string]bool
+type ErrIllegalItem struct {
+       err string
+       val interface{}
+}
+
+var (
+       methodSet map[string]bool
+)
+
+func (e *ErrIllegalItem) Error() string {
+       return fmt.Sprintf("illegal item : %v , msg: %s", e.val, e.err)
+}
 
 func (d *Validator) Validate(kind string, spec interface{}) error {
        switch kind {
@@ -22,7 +33,7 @@ func (d *Validator) Validate(kind string, spec interface{}) 
error {
        case "loadbalancer":
                return nil
        default:
-               return fmt.Errorf("not support kind yet")
+               return &ErrIllegalItem{"not support kind yet", kind}
        }
        return nil
 }
@@ -30,39 +41,39 @@ func (d *Validator) Validate(kind string, spec interface{}) 
error {
 func matchValidate(val interface{}) error {
        spec, ok := val.(map[string]interface{})
        if !ok {
-               return fmt.Errorf("illegal item : %v", val)
+               return &ErrIllegalItem{"can not cast to map", val}
        }
        if spec["matches"] == nil {
                return nil
        }
        matches, ok := spec["matches"].([]interface{})
        if !ok {
-               return fmt.Errorf("illegal item : %v", spec)
+               return &ErrIllegalItem{"don't have matches", spec}
        }
        for _, match := range matches {
                match, ok := match.(map[string]interface{})
                if !ok {
-                       return fmt.Errorf("illegal item : %v", match)
+                       return &ErrIllegalItem{"match can not cast to map", 
match}
                }
                if match["name"] == nil {
-                       return fmt.Errorf("match's name can not be null : %v", 
match)
+                       return &ErrIllegalItem{"match's name can not be null", 
match}
                }
                if match["apiPath"] == nil && match["headers"] == nil && 
match["methods"] == nil {
-                       return fmt.Errorf("match must have a match item 
[apiPath/headers/methods] %v", match)
+                       return &ErrIllegalItem{"match must have a match item 
[apiPath/headers/methods]", match}
                }
                //apiPath & headers do not check
                if match["methods"] != nil {
                        methods, ok := match["methods"].([]interface{})
                        if !ok {
-                               return fmt.Errorf("illegal item : %v", match)
+                               return &ErrIllegalItem{"methods must be a 
list", match}
                        }
                        for _, method := range methods {
                                methodStr, ok := method.(string)
                                if !ok {
-                                       return fmt.Errorf("illegal item : %v", 
method)
+                                       return &ErrIllegalItem{"method must be 
a string", method}
                                }
                                if !methodSet[methodStr] {
-                                       return fmt.Errorf("method must be one 
of the GET/POST/PUT/DELETE: %v", match)
+                                       return &ErrIllegalItem{"method must be 
one of the GET/POST/PUT/DELETE", method}
                                }
                        }
                }
@@ -89,15 +100,15 @@ func rateLimitingValidate(val interface{}) error {
 func policyValidate(val interface{}) error {
        spec, ok := val.(map[string]interface{})
        if !ok {
-               return fmt.Errorf("illegal item : %v", val)
+               return &ErrIllegalItem{"policy can not cast to map", val}
        }
        if spec["rules"] != nil {
                rules, ok := spec["rules"].(map[string]interface{})
                if !ok {
-                       return fmt.Errorf("illegal item : %v", spec)
+                       return &ErrIllegalItem{"policy's rules can not cast to 
map", spec}
                }
                if "" == rules["match"] {
-                       return fmt.Errorf("policy's match can not be nil: %v", 
spec)
+                       return &ErrIllegalItem{"policy's rules match can not be 
nil", spec}
                }
        }
        return nil
diff --git a/server/service/gov/mock/mock.go b/server/service/gov/mock/mock.go
index 0ee948f..bdf34ca 100644
--- a/server/service/gov/mock/mock.go
+++ b/server/service/gov/mock/mock.go
@@ -69,14 +69,14 @@ func (d *Distributor) Delete(id, project string) error {
 func (d *Distributor) Display(project, app, env string) ([]byte, error) {
        list := make([]*gov.Policy, 0)
        for _, g := range d.lbPolicies {
-               if g.Kind == MatchGroup && g.Selector.App == app && 
g.Selector.Environment == env {
+               if checkPolicy(g, MatchGroup, app, env) {
                        list = append(list, g)
                }
        }
        policyMap := make(map[string]*gov.Policy)
        for _, g := range d.lbPolicies {
                for _, kind := range PolicyNames {
-                       if g.Kind == kind && g.Selector.App == app && 
g.Selector.Environment == env {
+                       if checkPolicy(g, kind, app, env) {
                                policyMap[g.Name+kind] = g
                        }
                }
@@ -98,7 +98,7 @@ func (d *Distributor) Display(project, app, env string) 
([]byte, error) {
 func (d *Distributor) List(kind, project, app, env string) ([]byte, error) {
        r := make([]*gov.Policy, 0, len(d.lbPolicies))
        for _, g := range d.lbPolicies {
-               if g.Kind == kind && g.Selector.App == app && 
g.Selector.Environment == env {
+               if checkPolicy(g, kind, app, env) {
                        r = append(r, g)
                }
        }
@@ -106,6 +106,10 @@ func (d *Distributor) List(kind, project, app, env string) 
([]byte, error) {
        return b, nil
 }
 
+func checkPolicy(g *gov.Policy, kind, app, env string) bool {
+       return g.Kind == kind && g.Selector.App == app && 
g.Selector.Environment == env
+}
+
 func (d *Distributor) Get(kind, id, project string) ([]byte, error) {
        r := d.lbPolicies[id]
        if r == nil {

Reply via email to