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 e1239d1  [SCD-2133] add new display data interface (#787)
e1239d1 is described below

commit e1239d18cb22e22e7bd8865f81e27209fc6360d9
Author: GuoYL <[email protected]>
AuthorDate: Thu Dec 31 14:57:48 2020 +0800

    [SCD-2133] add new display data interface (#787)
    
    * [SCD-2133] add new display data interface
    
    * [SCD-2133] validate change / return 400 when error
    
    * [SCD-2133] modify governance create return type
    
    * [SCD-2133] add ut
    
    * [SCD-2133] add all env
    
    * [SCD-2133] modify ut
---
 pkg/gov/governance.go                         |   7 ++
 server/resource/v1/gov_resource.go            |  47 ++++++--
 server/service/gov/config_distributor.go      |  26 +++--
 server/service/gov/config_distributor_test.go |  71 +++++++++++-
 server/service/gov/kie/kie_distributor.go     | 159 ++++++++++++++++++--------
 server/service/gov/kie/validate.go            |  21 ++--
 server/service/gov/mock/mock.go               |  67 +++++++++--
 7 files changed, 312 insertions(+), 86 deletions(-)

diff --git a/pkg/gov/governance.go b/pkg/gov/governance.go
index d2eb4a0..dd8682a 100644
--- a/pkg/gov/governance.go
+++ b/pkg/gov/governance.go
@@ -30,9 +30,16 @@ type GovernancePolicy struct {
        Selector   Selector `json:"selector,omitempty"`
 }
 
+//DisplayData define display data
+type DisplayData struct {
+       Policies   []*Policy `json:"policies,omitempty"`
+       MatchGroup *Policy   `json:"matchGroup,omitempty"`
+}
+
 //Policy define policy and fault tolerant policy
 type Policy struct {
        *GovernancePolicy
+       Kind string      `json:"kind,omitempty"`
        Spec interface{} `json:"spec,omitempty"`
 }
 
diff --git a/server/resource/v1/gov_resource.go 
b/server/resource/v1/gov_resource.go
index 16694e0..81f1579 100644
--- a/server/resource/v1/gov_resource.go
+++ b/server/resource/v1/gov_resource.go
@@ -37,6 +37,7 @@ const (
        KindKey        = ":kind"
        ProjectKey     = ":project"
        IDKey          = ":id"
+       DisplayKey     = "display"
 )
 
 //Create gov config
@@ -49,9 +50,18 @@ func (t *Governance) Create(w http.ResponseWriter, req 
*http.Request) {
                controller.WriteError(w, discovery.ErrInternal, err.Error())
                return
        }
-       err = gov.Create(kind, project, body)
+       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())
+               return
+       }
+       _, err = w.Write(id)
+       if err != nil {
+               w.WriteHeader(http.StatusBadRequest)
+               log.Error("", err)
                controller.WriteError(w, discovery.ErrInternal, err.Error())
                return
        }
@@ -71,28 +81,39 @@ func (t *Governance) Put(w http.ResponseWriter, req 
*http.Request) {
        }
        err = gov.Update(id, kind, project, body)
        if err != nil {
-               log.Error("create gov err", err)
+               log.Error("put gov err", err)
+               w.WriteHeader(http.StatusBadRequest)
                controller.WriteError(w, discovery.ErrInternal, err.Error())
                return
        }
        w.WriteHeader(http.StatusOK)
 }
 
-//List return all gov config
-func (t *Governance) List(w http.ResponseWriter, req *http.Request) {
+//ListOrDisPlay return all gov config
+func (t *Governance) ListOrDisPlay(w http.ResponseWriter, req *http.Request) {
        kind := req.URL.Query().Get(KindKey)
        project := req.URL.Query().Get(ProjectKey)
        app := req.URL.Query().Get(AppKey)
        environment := req.URL.Query().Get(EnvironmentKey)
-       body, err := gov.List(kind, project, app, environment)
+       var body []byte
+       var err error
+       if kind == DisplayKey {
+               body, err = gov.Display(project, app, environment)
+       } else {
+               body, err = gov.List(kind, project, app, environment)
+       }
        if err != nil {
-               log.Error("create gov err", err)
+               log.Error("list gov err", err)
+               w.WriteHeader(http.StatusBadRequest)
                controller.WriteError(w, discovery.ErrInternal, err.Error())
                return
        }
        _, err = w.Write(body)
        if err != nil {
+               w.WriteHeader(http.StatusBadRequest)
                log.Error("", err)
+               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               return
        }
        w.WriteHeader(http.StatusOK)
        w.Header().Set(rest.HeaderContentType, rest.ContentTypeJSON)
@@ -100,17 +121,22 @@ func (t *Governance) List(w http.ResponseWriter, req 
*http.Request) {
 
 //Get gov config
 func (t *Governance) Get(w http.ResponseWriter, req *http.Request) {
+       kind := req.URL.Query().Get(KindKey)
        id := req.URL.Query().Get(IDKey)
        project := req.URL.Query().Get(ProjectKey)
-       body, err := gov.Get(id, project)
+       body, err := gov.Get(kind, id, project)
        if err != nil {
-               log.Error("create gov err", err)
+               w.WriteHeader(http.StatusBadRequest)
+               log.Error("get gov err", err)
                controller.WriteError(w, discovery.ErrInternal, err.Error())
                return
        }
        _, err = w.Write(body)
        if err != nil {
+               w.WriteHeader(http.StatusBadRequest)
                log.Error("", err)
+               controller.WriteError(w, discovery.ErrInternal, err.Error())
+               return
        }
        w.WriteHeader(http.StatusOK)
        w.Header().Set(rest.HeaderContentType, rest.ContentTypeJSON)
@@ -122,7 +148,8 @@ func (t *Governance) Delete(w http.ResponseWriter, req 
*http.Request) {
        project := req.URL.Query().Get(ProjectKey)
        err := gov.Delete(id, project)
        if err != nil {
-               log.Error("create gov err", err)
+               w.WriteHeader(http.StatusBadRequest)
+               log.Error("delete gov err", err)
                controller.WriteError(w, discovery.ErrInternal, err.Error())
                return
        }
@@ -135,7 +162,7 @@ func (t *Governance) URLPatterns() []rest.Route {
                //servicecomb.rateLimiter.{name}
                //....
                {Method: http.MethodPost, Path: "/v1/:project/gov/" + KindKey, 
Func: t.Create},
-               {Method: http.MethodGet, Path: "/v1/:project/gov/" + KindKey, 
Func: t.List},
+               {Method: http.MethodGet, Path: "/v1/:project/gov/" + KindKey, 
Func: t.ListOrDisPlay},
                {Method: http.MethodGet, Path: "/v1/:project/gov/" + KindKey + 
"/" + IDKey, Func: t.Get},
                {Method: http.MethodPut, Path: "/v1/:project/gov/" + KindKey + 
"/" + IDKey, Func: t.Put},
                {Method: http.MethodDelete, Path: "/v1/:project/gov/" + KindKey 
+ "/" + IDKey, Func: t.Delete},
diff --git a/server/service/gov/config_distributor.go 
b/server/service/gov/config_distributor.go
index c1c4224..45d4c7e 100644
--- a/server/service/gov/config_distributor.go
+++ b/server/service/gov/config_distributor.go
@@ -38,11 +38,12 @@ var distributorPlugins = map[string]NewDistributors{}
 //or service mesh system like istio, linkerd.
 //ConfigDistributor will convert standard servicecomb gov config to concrete 
spec, that data plane can recognize.
 type ConfigDistributor interface {
-       Create(kind, project string, spec []byte) error
+       Create(kind, project string, spec []byte) ([]byte, error)
        Update(id, kind, project string, spec []byte) error
        Delete(id, project string) error
+       Display(project, app, env string) ([]byte, error)
        List(kind, project, app, env string) ([]byte, error)
-       Get(id, project string) ([]byte, error)
+       Get(kind, id, project string) ([]byte, error)
        Type() string
        Name() string
 }
@@ -74,15 +75,11 @@ func Init() error {
        return nil
 }
 
-func Create(kind, project string, spec []byte) error {
-       var err error
+func Create(kind, project string, spec []byte) ([]byte, error) {
        for _, cd := range distributors {
-               err = cd.Create(kind, project, spec)
-               if err != nil {
-                       return err
-               }
+               return cd.Create(kind, project, spec)
        }
-       return nil
+       return nil, nil
 }
 
 func List(kind, project, app, env string) ([]byte, error) {
@@ -92,9 +89,16 @@ func List(kind, project, app, env string) ([]byte, error) {
        return nil, nil
 }
 
-func Get(id, project string) ([]byte, error) {
+func Display(project, app, env string) ([]byte, error) {
+       for _, cd := range distributors {
+               return cd.Display(project, app, env)
+       }
+       return nil, nil
+}
+
+func Get(kind, id, project string) ([]byte, error) {
        for _, cd := range distributors {
-               return cd.Get(id, project)
+               return cd.Get(kind, id, project)
        }
        return nil, nil
 }
diff --git a/server/service/gov/config_distributor_test.go 
b/server/service/gov/config_distributor_test.go
index fbb0d73..a5a38df 100644
--- a/server/service/gov/config_distributor_test.go
+++ b/server/service/gov/config_distributor_test.go
@@ -28,7 +28,15 @@ import (
        "github.com/stretchr/testify/assert"
 )
 
-func TestCreate(t *testing.T) {
+const Project = "default"
+const MockKind = "default"
+const MatchGroup = "match-group"
+const MockEnv = ""
+const MockApp = ""
+
+var id = ""
+
+func init() {
        config.Configurations = &config.Config{
                Gov: &config.Gov{
                        DistOptions: []config.DistributorOptions{
@@ -40,13 +48,72 @@ func TestCreate(t *testing.T) {
                },
        }
        err := svc.Init()
+       if err != nil {
+               panic(err)
+       }
+}
+
+func TestCreate(t *testing.T) {
+       b, _ := json.MarshalIndent(&gov.Policy{
+               GovernancePolicy: &gov.GovernancePolicy{
+                       Name: "Traffic2adminAPI",
+               },
+               Spec: &gov.LBSpec{RetryNext: 3, MarkerName: "traffic2adminAPI"},
+       }, "", "  ")
+       res, err := svc.Create(MockKind, Project, b)
+       id = string(res)
        assert.NoError(t, err)
+}
+
+func TestUpdate(t *testing.T) {
        b, _ := json.MarshalIndent(&gov.Policy{
                GovernancePolicy: &gov.GovernancePolicy{
                        Name: "Traffic2adminAPI",
                },
                Spec: &gov.LBSpec{RetryNext: 3, MarkerName: "traffic2adminAPI"},
        }, "", "  ")
-       err = svc.Create("lb", "default", b)
+       err := svc.Update(id, MockKind, Project, b)
+       assert.NoError(t, err)
+}
+
+func TestDisplay(t *testing.T) {
+       b, _ := json.MarshalIndent(&gov.Policy{
+               GovernancePolicy: &gov.GovernancePolicy{
+                       Name: "Traffic2adminAPI",
+               },
+       }, "", "  ")
+       res, err := svc.Create(MatchGroup, Project, b)
+       id = string(res)
+       assert.NoError(t, err)
+       policies := &[]*gov.DisplayData{}
+       res, err = svc.Display(Project, MockApp, MockEnv)
+       assert.NoError(t, err)
+       err = json.Unmarshal(res, policies)
+       assert.NoError(t, err)
+       assert.NotEmpty(t, policies)
+}
+
+func TestList(t *testing.T) {
+       policies := &[]*gov.Policy{}
+       res, err := svc.List(MockKind, Project, MockApp, MockEnv)
+       assert.NoError(t, err)
+       err = json.Unmarshal(res, policies)
+       assert.NoError(t, err)
+       assert.NotEmpty(t, policies)
+}
+
+func TestGet(t *testing.T) {
+       policy := &gov.Policy{}
+       res, err := svc.Get(MockKind, id, Project)
+       assert.NoError(t, err)
+       err = json.Unmarshal(res, policy)
+       assert.NoError(t, err)
+       assert.NotNil(t, policy)
+}
+
+func TestDelete(t *testing.T) {
+       err := svc.Delete(id, Project)
        assert.NoError(t, err)
+       res, _ := svc.Get(MockKind, id, Project)
+       assert.Nil(t, res)
 }
diff --git a/server/service/gov/kie/kie_distributor.go 
b/server/service/gov/kie/kie_distributor.go
index df43e31..0fc5bd0 100644
--- a/server/service/gov/kie/kie_distributor.go
+++ b/server/service/gov/kie/kie_distributor.go
@@ -5,9 +5,10 @@ import (
        "context"
        "encoding/json"
        "fmt"
-       "log"
        "strings"
 
+       "github.com/apache/servicecomb-service-center/pkg/log"
+
        "github.com/apache/servicecomb-service-center/pkg/gov"
        "github.com/apache/servicecomb-service-center/server/config"
        svc "github.com/apache/servicecomb-service-center/server/service/gov"
@@ -23,29 +24,33 @@ type Distributor struct {
 
 const (
        PREFIX         = "servicecomb."
+       MatchGroup     = "match-group"
        EnableStatus   = "enabled"
        ValueType      = "text"
        AppKey         = "app"
        EnvironmentKey = "environment"
+       EnvAll         = "all"
 )
 
+var PolicyNames = []string{"retry", "rateLimiting", "circuitBreaker", 
"bulkhead"}
+
 var rule = Validator{}
 
-func (d *Distributor) Create(kind, project string, spec []byte) error {
+func (d *Distributor) Create(kind, project string, spec []byte) ([]byte, 
error) {
        p := &gov.Policy{}
        err := json.Unmarshal(spec, p)
        if err != nil {
-               return err
+               return nil, err
        }
-       log.Println(fmt.Sprintf("create %v", &p))
+       log.Info(fmt.Sprintf("create %v", &p))
        key := toSnake(kind) + "." + p.Name
        err = rule.Validate(kind, p.Spec)
        if err != nil {
-               return err
+               return nil, err
        }
        yamlByte, err := yaml.Marshal(p.Spec)
        if err != nil {
-               return err
+               return nil, err
        }
        kv := kie.KVRequest{
                Key:       PREFIX + key,
@@ -54,13 +59,14 @@ func (d *Distributor) Create(kind, project string, spec 
[]byte) error {
                ValueType: ValueType,
                Labels:    map[string]string{AppKey: p.Selector.App, 
EnvironmentKey: p.Selector.Environment},
        }
-       _, err = d.client.Create(context.TODO(), kv, kie.WithProject(project))
+       res, err := d.client.Create(context.TODO(), kv, 
kie.WithProject(project))
        if err != nil {
-               log.Fatal("kie create failed", err)
-               return err
+               log.Error("kie create failed", err)
+               return nil, err
        }
        d.lbPolicies[p.GovernancePolicy.Name] = p
-       return nil
+       b, _ := json.MarshalIndent(res.ID, "", "  ")
+       return b, nil
 }
 
 func (d *Distributor) Update(id, kind, project string, spec []byte) error {
@@ -69,7 +75,7 @@ func (d *Distributor) Update(id, kind, project string, spec 
[]byte) error {
        if err != nil {
                return err
        }
-       log.Println(fmt.Sprintf("update %v", &p))
+       log.Info(fmt.Sprintf("update %v", &p))
        err = rule.Validate(kind, p.Spec)
        if err != nil {
                return err
@@ -85,7 +91,7 @@ func (d *Distributor) Update(id, kind, project string, spec 
[]byte) error {
        }
        _, err = d.client.Put(context.TODO(), kv, kie.WithProject(project))
        if err != nil {
-               log.Fatal("kie update failed", err)
+               log.Error("kie update failed", err)
                return err
        }
        d.lbPolicies[p.GovernancePolicy.Name] = p
@@ -95,65 +101,80 @@ func (d *Distributor) Update(id, kind, project string, 
spec []byte) error {
 func (d *Distributor) Delete(id, project string) error {
        err := d.client.Delete(context.TODO(), id, kie.WithProject(project))
        if err != nil {
-               log.Fatal("kie delete failed", err)
+               log.Error("kie delete failed", err)
                return err
        }
        return nil
 }
 
+func (d *Distributor) Display(project, app, env string) ([]byte, error) {
+       list, _, err := d.listDataByKind(MatchGroup, project, app, env)
+       if err != nil {
+               return nil, err
+       }
+       policyMap := make(map[string]*gov.Policy)
+       for _, kind := range PolicyNames {
+               policies, _, err := d.listDataByKind(kind, project, app, env)
+               if err != nil {
+                       continue
+               }
+               for _, policy := range policies.Data {
+                       item, err := d.transform(policy, kind)
+                       if err != nil {
+                               continue
+                       }
+                       policyMap[item.Name+kind] = item
+               }
+       }
+       r := make([]*gov.DisplayData, 0, list.Total)
+       for _, item := range list.Data {
+               match, err := d.transform(item, MatchGroup)
+               if err != nil {
+                       return nil, err
+               }
+               var policies []*gov.Policy
+               for _, kind := range PolicyNames {
+                       if policyMap[match.Name+kind] != nil {
+                               policies = append(policies, 
policyMap[match.Name+kind])
+                       }
+               }
+               result := &gov.DisplayData{
+                       Policies:   policies,
+                       MatchGroup: match,
+               }
+               r = append(r, result)
+       }
+       b, _ := json.MarshalIndent(r, "", "  ")
+       return b, nil
+}
+
 func (d *Distributor) List(kind, project, app, env string) ([]byte, error) {
-       list, _, err := d.client.List(context.TODO(),
-               kie.WithKey("beginWith("+PREFIX+toSnake(kind)+")"),
-               kie.WithLabels(map[string]string{AppKey: app, EnvironmentKey: 
env}),
-               kie.WithRevision(0),
-               kie.WithGetProject(project))
+       list, _, err := d.listDataByKind(kind, project, app, env)
        if err != nil {
                return nil, err
        }
        r := make([]*gov.Policy, 0, list.Total)
        for _, item := range list.Data {
-               goc := &gov.Policy{
-                       GovernancePolicy: &gov.GovernancePolicy{},
-               }
-               spec := make(map[string]interface{})
-               specJSON, _ := yaml.YAMLToJSON([]byte(item.Value))
-               err = json.Unmarshal(specJSON, &spec)
+               policy, err := d.transform(item, kind)
                if err != nil {
-                       log.Fatal("kie list failed", err)
                        return nil, err
                }
-               goc.ID = item.ID
-               goc.Status = item.Status
-               goc.Name = item.Key
-               goc.Spec = spec
-               goc.Selector.App = item.Labels[AppKey]
-               goc.Selector.Environment = item.Labels[EnvironmentKey]
-               goc.CreatTime = item.CreatTime
-               goc.UpdateTime = item.UpdateTime
-               r = append(r, goc)
+               r = append(r, policy)
        }
        b, _ := json.MarshalIndent(r, "", "  ")
        return b, nil
 }
 
-func (d *Distributor) Get(id, project string) ([]byte, error) {
+func (d *Distributor) Get(kind, id, project string) ([]byte, error) {
        kv, err := d.client.Get(context.TODO(), id, kie.WithGetProject(project))
        if err != nil {
-               log.Fatal("kie get failed", err)
                return nil, err
        }
-       goc := &gov.Policy{
-               GovernancePolicy: &gov.GovernancePolicy{},
+       policy, err := d.transform(kv, kind)
+       if err != nil {
+               return nil, err
        }
-       goc.ID = kv.ID
-       goc.Status = kv.Status
-       goc.Name = kv.Key
-       goc.Spec = kv
-       goc.Selector.App = kv.Labels[AppKey]
-       goc.Selector.Environment = kv.Labels[EnvironmentKey]
-       goc.CreatTime = kv.CreatTime
-       goc.UpdateTime = kv.UpdateTime
-       b, _ := json.MarshalIndent(goc, "", "  ")
+       b, _ := json.MarshalIndent(policy, "", "  ")
        return b, nil
 }
 
@@ -170,7 +191,7 @@ func initClient(endpoint string) *kie.Client {
                        DefaultLabels: map[string]string{},
                })
        if err != nil {
-               log.Fatalf("init kie client failed, err: %s", err)
+               log.Fatal("init kie client failed, err: %s", err)
        }
        return client
 }
@@ -201,6 +222,48 @@ func toSnake(name string) string {
        return buffer.String()
 }
 
+func (d *Distributor) listDataByKind(kind, project, app, env string) 
(*kie.KVResponse, int, error) {
+       ops := []kie.GetOption{
+               kie.WithKey("beginWith(" + PREFIX + toSnake(kind) + ")"),
+               kie.WithRevision(0),
+               kie.WithGetProject(project),
+       }
+       labels := map[string]string{}
+       if env != EnvAll {
+               labels[EnvironmentKey] = env
+       }
+       if app != "" {
+               labels[AppKey] = app
+       }
+       if len(labels) > 0 {
+               ops = append(ops, kie.WithLabels(labels))
+       }
+       return d.client.List(context.TODO(), ops...)
+}
+
+func (d *Distributor) transform(kv *kie.KVDoc, kind string) (*gov.Policy, 
error) {
+       goc := &gov.Policy{
+               GovernancePolicy: &gov.GovernancePolicy{},
+       }
+       spec := make(map[string]interface{})
+       specJSON, _ := yaml.YAMLToJSON([]byte(kv.Value))
+       err := json.Unmarshal(specJSON, &spec)
+       if err != nil {
+               log.Fatal("kie transform kv failed", err)
+               return nil, err
+       }
+       goc.Kind = kind
+       goc.ID = kv.ID
+       goc.Status = kv.Status
+       goc.Name = kv.Key[strings.LastIndex(kv.Key, ".")+1 : len(kv.Key)]
+       goc.Spec = spec
+       goc.Selector.App = kv.Labels[AppKey]
+       goc.Selector.Environment = kv.Labels[EnvironmentKey]
+       goc.CreatTime = kv.CreatTime
+       goc.UpdateTime = kv.UpdateTime
+       return goc, nil
+}
+
 func init() {
        svc.InstallDistributor(svc.ConfigDistributorKie, new)
 }
diff --git a/server/service/gov/kie/validate.go 
b/server/service/gov/kie/validate.go
index fb9f0b4..bafe794 100644
--- a/server/service/gov/kie/validate.go
+++ b/server/service/gov/kie/validate.go
@@ -15,9 +15,9 @@ func (d *Validator) Validate(kind string, spec interface{}) 
error {
                return matchValidate(spec)
        case "retry":
                return retryValidate(spec)
-       case "rateLimiting":
+       case "rate-limiting":
                return rateLimitingValidate(spec)
-       case "circuitBreaker":
+       case "circuit-breaker":
        case "bulkhead":
        case "loadbalancer":
                return nil
@@ -32,6 +32,9 @@ func matchValidate(val interface{}) error {
        if !ok {
                return fmt.Errorf("illegal item : %v", val)
        }
+       if spec["matches"] == nil {
+               return nil
+       }
        matches, ok := spec["matches"].([]interface{})
        if !ok {
                return fmt.Errorf("illegal item : %v", spec)
@@ -88,12 +91,14 @@ func policyValidate(val interface{}) error {
        if !ok {
                return fmt.Errorf("illegal item : %v", val)
        }
-       rules, ok := spec["rules"].(map[string]interface{})
-       if !ok {
-               return fmt.Errorf("illegal item : %v", spec)
-       }
-       if "" == rules["match"] {
-               return fmt.Errorf("policy's match can not be nil: %v", spec)
+       if spec["rules"] != nil {
+               rules, ok := spec["rules"].(map[string]interface{})
+               if !ok {
+                       return fmt.Errorf("illegal item : %v", spec)
+               }
+               if "" == rules["match"] {
+                       return fmt.Errorf("policy's match can not be nil: %v", 
spec)
+               }
        }
        return nil
 }
diff --git a/server/service/gov/mock/mock.go b/server/service/gov/mock/mock.go
index cc6359c..0ee948f 100644
--- a/server/service/gov/mock/mock.go
+++ b/server/service/gov/mock/mock.go
@@ -22,6 +22,8 @@ import (
        "fmt"
        "log"
 
+       uuid "github.com/satori/go.uuid"
+
        "github.com/apache/servicecomb-service-center/pkg/gov"
        "github.com/apache/servicecomb-service-center/server/config"
        svc "github.com/apache/servicecomb-service-center/server/service/gov"
@@ -32,36 +34,87 @@ type Distributor struct {
        name       string
 }
 
-func (d *Distributor) Create(kind, project string, spec []byte) error {
+const MatchGroup = "match-group"
+
+var PolicyNames = []string{"retry", "rateLimiting", "circuitBreaker", 
"bulkhead"}
+
+func (d *Distributor) Create(kind, project string, spec []byte) ([]byte, 
error) {
        p := &gov.Policy{}
        err := json.Unmarshal(spec, p)
+       p.ID = uuid.NewV4().String()
+       p.Kind = kind
        log.Println(fmt.Sprintf("create %v", &p))
-       d.lbPolicies[p.GovernancePolicy.Name] = p
-       return err
+       d.lbPolicies[p.GovernancePolicy.ID] = p
+       return []byte(p.ID), err
 }
+
 func (d *Distributor) Update(id, kind, project string, spec []byte) error {
+       if d.lbPolicies[id] == nil {
+               return fmt.Errorf("id not exsit")
+       }
        p := &gov.Policy{}
        err := json.Unmarshal(spec, p)
+       p.ID = id
+       p.Kind = kind
        log.Println("update ", p)
-       d.lbPolicies[p.GovernancePolicy.Name] = p
+       d.lbPolicies[p.GovernancePolicy.ID] = p
        return err
 }
+
 func (d *Distributor) Delete(id, project string) error {
        delete(d.lbPolicies, id)
        return nil
 }
+
+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 {
+                       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 {
+                               policyMap[g.Name+kind] = g
+                       }
+               }
+       }
+       r := make([]*gov.DisplayData, 0, len(list))
+       for _, g := range list {
+               policies := make([]*gov.Policy, 0)
+               for _, kind := range PolicyNames {
+                       policies = append(policies, policyMap[g.Name+kind])
+               }
+               r = append(r, &gov.DisplayData{
+                       MatchGroup: g,
+                       Policies:   policies,
+               })
+       }
+       b, _ := json.MarshalIndent(r, "", "  ")
+       return b, nil
+}
 func (d *Distributor) List(kind, project, app, env string) ([]byte, error) {
        r := make([]*gov.Policy, 0, len(d.lbPolicies))
        for _, g := range d.lbPolicies {
-               r = append(r, g)
+               if g.Kind == kind && g.Selector.App == app && 
g.Selector.Environment == env {
+                       r = append(r, g)
+               }
        }
        b, _ := json.MarshalIndent(r, "", "  ")
        return b, nil
 }
 
-func (d *Distributor) Get(id, project string) ([]byte, error) {
-       return nil, nil
+func (d *Distributor) Get(kind, id, project string) ([]byte, error) {
+       r := d.lbPolicies[id]
+       if r == nil {
+               return nil, nil
+       }
+       b, _ := json.MarshalIndent(r, "", "  ")
+       return b, nil
 }
+
 func (d *Distributor) Type() string {
        return svc.ConfigDistributorMock
 }

Reply via email to