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 {