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

littlecui 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 ab1cc9f6 [fix]failed to create match-group policy (#1335) (#1336)
ab1cc9f6 is described below

commit ab1cc9f6fb49634e7d8e37bf18e20c5c68964b14
Author: little-cui <[email protected]>
AuthorDate: Wed Aug 31 15:39:52 2022 +0800

    [fix]failed to create match-group policy (#1335) (#1336)
    
    * [fix]failed to create match-group policy
    
    * [fix]failed to create match-group policy
---
 etc/conf/grc.json                                  | 138 ++++++++++++++
 examples/dev/conf/app.yaml                         |   7 +-
 server/bootstrap/bootstrap.go                      |   1 -
 server/config/config.go                            |  33 +++-
 server/config/config_test.go                       |  61 +++++--
 server/config/types.go                             |   9 +-
 server/ext/policy/builtin.go                       | 199 ---------------------
 server/resource/gov/gov_resource.go                |  12 +-
 server/resource/gov/gov_resource_test.go           |  22 ++-
 server/service/grc/config_distributor.go           |  23 ++-
 server/service/grc/config_distributor_test.go      |  10 +-
 server/service/grc/kie/kie_distributor.go          |  14 +-
 server/service/grc/mock/mock.go                    |  14 +-
 server/service/grc/policy.go                       |   7 +-
 server/service/grc/validate.go                     |  13 --
 .../grc/validate_test.go}                          |  27 +--
 16 files changed, 294 insertions(+), 296 deletions(-)

diff --git a/etc/conf/grc.json b/etc/conf/grc.json
new file mode 100644
index 00000000..4fd49556
--- /dev/null
+++ b/etc/conf/grc.json
@@ -0,0 +1,138 @@
+{
+  "gov": {
+    "match-group": {
+      "validationSpec": {
+        "type": "object",
+        "required": [
+          "matches",
+          "alias"
+        ],
+        "properties": {
+          "alias": {
+            "type": "string",
+            "minLength": 1
+          },
+          "matches": {
+            "type": "array",
+            "minItems": 1,
+            "items": {
+              "type": "object",
+              "required": [
+                "name"
+              ],
+              "properties": {
+                "name": {
+                  "type": "string",
+                  "minLength": 1
+                },
+                "apiPath": {
+                  "type": "object",
+                  "minProperties": 1
+                },
+                "headers": {
+                  "type": "object"
+                },
+                "method": {
+                  "type": "array",
+                  "minItems": 1,
+                  "items": {
+                    "type": "string",
+                    "enum": [
+                      "GET",
+                      "POST",
+                      "DELETE",
+                      "PUT",
+                      "PATCH"
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "policies": {
+      "retry": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "maxAttempts"
+          ],
+          "properties": {
+            "retryOnSame": {
+              "type": "integer",
+              "minimum": 0
+            }
+          }
+        }
+      },
+      "rate-limiting": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "rate"
+          ]
+        }
+      },
+      "loadbalance": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "rule"
+          ],
+          "properties": {
+            "rule": {
+              "type": "string",
+              "minLength": 1
+            }
+          }
+        }
+      },
+      "circuit-breaker": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "minimumNumberOfCalls"
+          ],
+          "properties": {
+            "minimumNumberOfCalls": {
+              "type": "integer",
+              "minimum": 0
+            }
+          }
+        }
+      },
+      "instance-isolation": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "minimumNumberOfCalls"
+          ]
+        }
+      },
+      "fault-injection": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "percentage"
+          ],
+          "properties": {
+            "percentage": {
+              "type": "number",
+              "minimum": 0
+            }
+          }
+        }
+      },
+      "bulkhead": {
+        "validationSpec": {
+          "type": "object",
+          "required": [
+            "maxConcurrentCalls"
+          ]
+        }
+      }
+    }
+  }
+}
diff --git a/examples/dev/conf/app.yaml b/examples/dev/conf/app.yaml
index 2c1853df..9d5192f5 100644
--- a/examples/dev/conf/app.yaml
+++ b/examples/dev/conf/app.yaml
@@ -36,10 +36,9 @@ server:
     ipLookups: RemoteAddr,X-Forwarded-For,X-Real-IP
 
 gov:
-  plugins:
-    - name: kie
-      type: kie
-      endpoint: http://127.0.0.1:30110
+  kie:
+    type: kie
+    endpoint: http://127.0.0.1:30110
 
 log:
   # DEBUG, INFO, WARN, ERROR, FATAL
diff --git a/server/bootstrap/bootstrap.go b/server/bootstrap/bootstrap.go
index b9aeccc5..2882c9d5 100644
--- a/server/bootstrap/bootstrap.go
+++ b/server/bootstrap/bootstrap.go
@@ -60,7 +60,6 @@ import (
        _ "github.com/apache/servicecomb-service-center/server/rest/admin"
 
        //governance
-       _ "github.com/apache/servicecomb-service-center/server/ext/policy"
        _ "github.com/apache/servicecomb-service-center/server/service/grc/kie"
 
        //metrics
diff --git a/server/config/config.go b/server/config/config.go
index 0b0603e0..05178efc 100644
--- a/server/config/config.go
+++ b/server/config/config.go
@@ -20,16 +20,16 @@ package config
 import (
        "encoding/json"
        "fmt"
+       "os"
        "path/filepath"
        "runtime"
        "time"
 
-       "github.com/go-chassis/go-archaius"
-
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/plugin"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/version"
+       "github.com/go-chassis/go-archaius"
 )
 
 const (
@@ -93,7 +93,7 @@ func Init() {
 
        err = archaius.AddFile(filepath.Join(util.GetAppRoot(), "conf", 
"app.yaml"))
        if err != nil {
-               log.Warn(fmt.Sprintf("can not add config file source, error: 
%s", err))
+               log.Warn(fmt.Sprintf("can not add app config file source, 
error: %s", err))
        }
 
        err = Reload()
@@ -112,11 +112,18 @@ func Reload() error {
        if err != nil {
                return err
        }
+
        *Server = loadServerConfig()
        if GetLog().LogLevel == "DEBUG" {
                body, _ := json.MarshalIndent(archaius.GetConfigs(), "", "  ")
                log.Debug(fmt.Sprintf("finish to reload configurations\n%s", 
body))
        }
+
+       grcCfg := loadGrcConfig()
+       if grcCfg != nil {
+               App.Gov.MatchGroup = grcCfg.MatchGroup
+               App.Gov.Policies = grcCfg.Policies
+       }
        return nil
 }
 
@@ -187,3 +194,23 @@ func setCPUs() {
        runtime.GOMAXPROCS(cores)
        log.Info(fmt.Sprintf("service center is running simultaneously with %d 
CPU cores", cores))
 }
+
+func loadGrcConfig() *Gov {
+       grcFile := filepath.Join(util.GetAppRoot(), "conf", "grc.json")
+       bytes, err := os.ReadFile(grcFile)
+       if err != nil {
+               log.Warn(fmt.Sprintf("can not add grc config file source, 
error: %s", err))
+               return nil
+       }
+       var policies AppConfig
+       err = json.Unmarshal(bytes, &policies)
+       if err != nil {
+               log.Error("unmarshal grc config failed", err)
+               return nil
+       }
+       if policies.Gov == nil {
+               log.Warn("no grc config load")
+               return nil
+       }
+       return policies.Gov
+}
diff --git a/server/config/config_test.go b/server/config/config_test.go
index f832fd3f..d4c1cf39 100644
--- a/server/config/config_test.go
+++ b/server/config/config_test.go
@@ -31,24 +31,63 @@ import (
 
 func TestInit(t *testing.T) {
        defer archaius.Clean()
-       b := []byte(`
-gov:
-  kieSever1:
-   type: kie
-   endpoint: 127.0.0.1:30110
 
-`)
        dir := filepath.Join(util.GetAppRoot(), "conf")
-       defer os.Remove(dir)
        os.Mkdir(dir, 0750)
-       file := filepath.Join(dir, "app.yaml")
-       defer os.Remove(file)
-       f1, err := os.Create(file)
+       defer os.Remove(dir)
+
+       govFile := filepath.Join(dir, "app.yaml")
+       f1, err := os.Create(govFile)
+       assert.NoError(t, err)
+       defer os.Remove(govFile)
+       _, err = io.WriteString(f1, `
+gov:
+  kieSever1:
+    type: kie
+    endpoint: 127.0.0.1:30110
+`)
        assert.NoError(t, err)
-       _, err = io.WriteString(f1, string(b))
+
+       policyFile := filepath.Join(dir, "grc.json")
+       f2, err := os.Create(policyFile)
        assert.NoError(t, err)
+       defer os.Remove(policyFile)
+       _, err = io.WriteString(f2, `
+{
+  "gov": {
+    "match-group": {
+      "validationSpec": {
+        "type": "object",
+        "properties": {
+          "alias": {
+            "type": "string",
+            "minLength": 1
+          }
+        }
+      }
+    },
+    "policies": {
+      "retry": {
+        "validationSpec": {
+          "type": "object",
+          "properties": {
+            "retryOnSame": {
+              "type": "integer",
+              "minimum": 0
+            }
+          }
+        }
+      }
+    }
+  }
+}`)
+       assert.NoError(t, err)
+
        config.Init()
        assert.NoError(t, err)
        assert.Equal(t, "kie", config.GetGov().DistMap["kieSever1"].Type)
        assert.Equal(t, "127.0.0.1:30110", 
config.GetGov().DistMap["kieSever1"].Endpoint)
+
+       assert.NotNil(t, config.GetGov().Policies["match-group"])
+       assert.NotNil(t, config.GetGov().Policies["policies"])
 }
diff --git a/server/config/types.go b/server/config/types.go
index 492a9d3f..c5c4bd81 100644
--- a/server/config/types.go
+++ b/server/config/types.go
@@ -19,6 +19,7 @@ package config
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/plugin"
+       "k8s.io/kube-openapi/pkg/validation/spec"
 )
 
 const (
@@ -32,7 +33,13 @@ type AppConfig struct {
        Server *ServerConfig `yaml:"server"`
 }
 type Gov struct {
-       DistMap map[string]DistributorOptions `yaml:",inline"`
+       DistMap    map[string]DistributorOptions `json:"-" yaml:",inline"`
+       MatchGroup *Policy                       `json:"match-group" yaml:"-"`
+       Policies   Policies                      `yaml:"-"`
+}
+type Policies map[string]Policy
+type Policy struct {
+       ValidationSpec *spec.Schema
 }
 type DistributorOptions struct {
        Name     string `yaml:"name"`
diff --git a/server/ext/policy/builtin.go b/server/ext/policy/builtin.go
deleted file mode 100644
index b32c34ab..00000000
--- a/server/ext/policy/builtin.go
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package policy
-
-import (
-       "github.com/apache/servicecomb-service-center/server/service/grc"
-       "k8s.io/kube-openapi/pkg/validation/spec"
-)
-
-var (
-       notEmpty         = int64(1)
-       notNegative      = float64(0)
-       matchGroupSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"matches", "alias"},
-                       Properties: map[string]spec.Schema{
-                               "alias": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:      []string{"string"},
-                                               MinLength: &notEmpty,
-                                       },
-                               },
-                               "matches": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:     []string{"array"},
-                                               MinItems: &notEmpty,
-                                               Items: &spec.SchemaOrArray{
-                                                       Schema: &spec.Schema{
-                                                               SchemaProps: 
spec.SchemaProps{
-                                                                       Type:   
  []string{"object"},
-                                                                       
Required: []string{"name"},
-                                                                       
Properties: map[string]spec.Schema{
-                                                                               
"name": {
-                                                                               
        SchemaProps: spec.SchemaProps{
-                                                                               
                Type:      []string{"string"},
-                                                                               
                MinLength: &notEmpty,
-                                                                               
        },
-                                                                               
},
-                                                                               
"apiPath": {
-                                                                               
        SchemaProps: spec.SchemaProps{
-                                                                               
                Type:      []string{"string"},
-                                                                               
                MinLength: &notEmpty,
-                                                                               
        },
-                                                                               
},
-                                                                               
"method": {
-                                                                               
        SchemaProps: spec.SchemaProps{
-                                                                               
                Type:     []string{"array"},
-                                                                               
                MinItems: &notEmpty,
-                                                                               
                Items: &spec.SchemaOrArray{
-                                                                               
                        Schema: &spec.Schema{
-                                                                               
                                SchemaProps: spec.SchemaProps{
-                                                                               
                                        Type: []string{"string"},
-                                                                               
                                        Enum: []interface{}{"GET", "POST", 
"DELETE", "PUT", "PATCH"},
-                                                                               
                                },
-                                                                               
                        },
-                                                                               
                },
-                                                                               
        },
-                                                                               
},
-                                                                               
"headers": {
-                                                                               
        SchemaProps: spec.SchemaProps{
-                                                                               
                Type:          []string{"object"},
-                                                                               
                MinProperties: &notEmpty,
-                                                                               
        },
-                                                                               
},
-                                                                       },
-                                                               },
-                                                       },
-                                               },
-                                       },
-                               },
-                       },
-               }}
-       retrySchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:          []string{"object"},
-                       MinProperties: &notEmpty,
-                       Properties: map[string]spec.Schema{
-                               "maxAttempts": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"integer"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                               "retryOnSame": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"integer"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                       },
-               },
-       }
-       rateLimitingSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"rate"},
-                       Properties: map[string]spec.Schema{
-                               "rate": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"number"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                       },
-               },
-       }
-       loadbalanceSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"rule"},
-                       Properties: map[string]spec.Schema{
-                               "rule": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:      []string{"string"},
-                                               MinLength: &notEmpty,
-                                       },
-                               },
-                       },
-               }}
-       circuitBreakerSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"minimumNumberOfCalls"},
-                       Properties: map[string]spec.Schema{
-                               "minimumNumberOfCalls": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"integer"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                       },
-               }}
-       instanceIsolationSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"minimumNumberOfCalls"},
-                       Properties: map[string]spec.Schema{
-                               "minimumNumberOfCalls": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"integer"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                       },
-               }}
-       faultInjectionSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"percentage"},
-                       Properties: map[string]spec.Schema{
-                               "percentage": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"number"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                       },
-               }}
-       bulkheadSchema = &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"maxConcurrentCalls"},
-                       Properties: map[string]spec.Schema{
-                               "maxConcurrentCalls": {
-                                       SchemaProps: spec.SchemaProps{
-                                               Type:    []string{"integer"},
-                                               Minimum: &notNegative,
-                                       },
-                               },
-                       },
-               }}
-)
-
-func init() {
-       grc.RegisterPolicySchema("match-group", matchGroupSchema)
-       grc.RegisterPolicySchema("retry", retrySchema)
-       grc.RegisterPolicySchema("rate-limiting", rateLimitingSchema)
-       grc.RegisterPolicySchema("loadbalance", loadbalanceSchema)
-       grc.RegisterPolicySchema("circuit-breaker", circuitBreakerSchema)
-       grc.RegisterPolicySchema("instance-isolation", instanceIsolationSchema)
-       grc.RegisterPolicySchema("fault-injection", faultInjectionSchema)
-       grc.RegisterPolicySchema("bulkhead", bulkheadSchema)
-}
diff --git a/server/resource/gov/gov_resource.go 
b/server/resource/gov/gov_resource.go
index 3c639565..bf16fa09 100644
--- a/server/resource/gov/gov_resource.go
+++ b/server/resource/gov/gov_resource.go
@@ -70,11 +70,6 @@ func (t *Governance) Create(w http.ResponseWriter, r 
*http.Request) {
        }
        id, err := grc.Create(r.Context(), kind, project, p)
        if err != nil {
-               if _, ok := err.(*grc.ErrIllegalItem); ok {
-                       log.Error("", err)
-                       rest.WriteError(w, discovery.ErrInvalidParams, 
err.Error())
-                       return
-               }
                processError(w, err, "create gov data err")
                return
        }
@@ -102,18 +97,13 @@ func (t *Governance) Put(w http.ResponseWriter, r 
*http.Request) {
        }
        err = grc.ValidatePolicySpec(kind, p.Spec)
        if err != nil {
-               log.Error("validate policy err", err)
+               log.Error(fmt.Sprintf("validate policy [%s] err", kind), err)
                rest.WriteError(w, discovery.ErrInvalidParams, err.Error())
                return
        }
        log.Info(fmt.Sprintf("update %v", &p))
        err = grc.Update(r.Context(), kind, id, project, p)
        if err != nil {
-               if _, ok := err.(*grc.ErrIllegalItem); ok {
-                       log.Error("", err)
-                       rest.WriteError(w, discovery.ErrInvalidParams, 
err.Error())
-                       return
-               }
                processError(w, err, "put gov err")
                return
        }
diff --git a/server/resource/gov/gov_resource_test.go 
b/server/resource/gov/gov_resource_test.go
index 31cbe5b8..bf9a838d 100644
--- a/server/resource/gov/gov_resource_test.go
+++ b/server/resource/gov/gov_resource_test.go
@@ -24,6 +24,9 @@ import (
        "net/http/httptest"
        "testing"
 
+       _ "github.com/apache/servicecomb-service-center/server/service/grc/mock"
+       "k8s.io/kube-openapi/pkg/validation/spec"
+
        _ "github.com/apache/servicecomb-service-center/test"
 
        "github.com/apache/servicecomb-service-center/pkg/gov"
@@ -34,17 +37,18 @@ import (
        grcsvc "github.com/apache/servicecomb-service-center/server/service/grc"
        "github.com/go-chassis/go-archaius"
        "github.com/stretchr/testify/assert"
-
-       _ "github.com/apache/servicecomb-service-center/server/service/grc/mock"
-
-       _ "github.com/apache/servicecomb-service-center/server/ext/policy"
 )
 
 func init() {
        config.App.Gov = &config.Gov{
-               DistMap: map[string]config.DistributorOptions{
+               Policies: config.Policies{
                        "mock": {
-                               Type: "mock",
+                               ValidationSpec: &spec.Schema{
+                                       SchemaProps: spec.SchemaProps{
+                                               Type:     []string{"object"},
+                                               Required: []string{"rule"},
+                                       },
+                               },
                        },
                },
        }
@@ -53,11 +57,11 @@ func init() {
                log.Fatal("", err)
        }
 }
+
 func TestGovernance_Create(t *testing.T) {
        err := archaius.Init(archaius.WithMemorySource(), 
archaius.WithENVSource())
        assert.NoError(t, err)
 
-       grcsvc.Init()
        rest.RegisterServant(&v1.Governance{})
 
        t.Run("create load balancing, should success", func(t *testing.T) {
@@ -66,7 +70,7 @@ func TestGovernance_Create(t *testing.T) {
                        Spec: map[string]interface{}{
                                "rule": "rr",
                        }})
-               r, _ := http.NewRequest(http.MethodPost, 
"/v1/default/gov/loadbalance", bytes.NewBuffer(b))
+               r, _ := http.NewRequest(http.MethodPost, 
"/v1/default/gov/mock", bytes.NewBuffer(b))
                w := httptest.NewRecorder()
                rest.GetRouter().ServeHTTP(w, r)
                assert.Equal(t, http.StatusOK, w.Code)
@@ -75,7 +79,7 @@ func TestGovernance_Create(t *testing.T) {
                b, _ := json.Marshal(&gov.Policy{
                        GovernancePolicy: &gov.GovernancePolicy{Name: "test"},
                        Spec:             map[string]interface{}{}})
-               r, _ := http.NewRequest(http.MethodPost, 
"/v1/default/gov/loadbalance", bytes.NewBuffer(b))
+               r, _ := http.NewRequest(http.MethodPost, 
"/v1/default/gov/mock", bytes.NewBuffer(b))
                w := httptest.NewRecorder()
                rest.GetRouter().ServeHTTP(w, r)
                assert.Equal(t, http.StatusBadRequest, w.Code)
diff --git a/server/service/grc/config_distributor.go 
b/server/service/grc/config_distributor.go
index 88ec80d1..79fbb0e9 100644
--- a/server/service/grc/config_distributor.go
+++ b/server/service/grc/config_distributor.go
@@ -19,6 +19,7 @@ package grc
 
 import (
        "context"
+       "errors"
 
        model "github.com/apache/servicecomb-service-center/pkg/gov"
        "github.com/apache/servicecomb-service-center/pkg/log"
@@ -31,6 +32,8 @@ const (
        ConfigDistributorMock  = "mock"
 )
 
+var ErrNoConfig = errors.New("no gov config")
+
 type NewDistributors func(opts config.DistributorOptions) (ConfigDistributor, 
error)
 
 var distributors = map[string]ConfigDistributor{}
@@ -57,8 +60,13 @@ func InstallDistributor(t string, newDistributors 
NewDistributors) {
 }
 
 // Init create distributors according to gov config.
-// it may creates multiple distributors. and distribute policy one by one
+// it may creates multiple distributors and distribute policy one by one,
+// the policy config loaded from grc.json file.
 func Init() error {
+       if config.GetGov() == nil {
+               return ErrNoConfig
+       }
+
        for name, opts := range config.GetGov().DistMap {
                opts.Name = name
                f, ok := distributorPlugins[name]
@@ -73,6 +81,19 @@ func Init() error {
                }
                distributors[name+"::"+opts.Type] = cd
        }
+
+       if config.GetGov().MatchGroup != nil {
+               RegisterPolicySchema(KindMatchGroup, 
config.GetGov().MatchGroup.ValidationSpec)
+       }
+
+       if config.GetGov().Policies != nil {
+               var names []string
+               for kind, policy := range config.GetGov().Policies {
+                       RegisterPolicySchema(kind, policy.ValidationSpec)
+                       names = append(names, kind)
+               }
+               PolicyNames = names
+       }
        return nil
 }
 
diff --git a/server/service/grc/config_distributor_test.go 
b/server/service/grc/config_distributor_test.go
index 857e58c1..c79b5d6e 100644
--- a/server/service/grc/config_distributor_test.go
+++ b/server/service/grc/config_distributor_test.go
@@ -39,12 +39,10 @@ const MockApp = ""
 var id = ""
 
 func init() {
-       config.App = &config.AppConfig{
-               Gov: &config.Gov{
-                       DistMap: map[string]config.DistributorOptions{
-                               "mock": {
-                                       Type: "mock",
-                               },
+       config.App.Gov = &config.Gov{
+               DistMap: map[string]config.DistributorOptions{
+                       "mock": {
+                               Type: "mock",
                        },
                },
        }
diff --git a/server/service/grc/kie/kie_distributor.go 
b/server/service/grc/kie/kie_distributor.go
index 1ba1fab9..30ac7ba4 100644
--- a/server/service/grc/kie/kie_distributor.go
+++ b/server/service/grc/kie/kie_distributor.go
@@ -42,16 +42,6 @@ type Distributor struct {
        client *kie.Client
 }
 
-var PolicyNames = []string{
-       "retry",
-       "rateLimiting",
-       "circuitBreaker",
-       "instanceIsolation",
-       "faultInjection",
-       "bulkhead",
-       "loadbalance",
-}
-
 func (d *Distributor) Create(ctx context.Context, kind, project string, p 
*gov.Policy) ([]byte, error) {
        if kind == grcsvc.KindMatchGroup {
                err := d.generateID(ctx, project, p)
@@ -156,7 +146,7 @@ func (d *Distributor) Display(ctx context.Context, project, 
app, env string) ([]
                return nil, err
        }
        policyMap := make(map[string]*gov.Policy)
-       for _, kind := range PolicyNames {
+       for _, kind := range grcsvc.PolicyNames {
                policies, _, err := d.listDataByKind(ctx, kind, project, app, 
env)
                if err != nil {
                        continue
@@ -179,7 +169,7 @@ func (d *Distributor) Display(ctx context.Context, project, 
app, env string) ([]
 
                }
                var policies []*gov.Policy
-               for _, kind := range PolicyNames {
+               for _, kind := range grcsvc.PolicyNames {
                        if policyMap[match.Name+kind] != nil {
                                policies = append(policies, 
policyMap[match.Name+kind])
                        }
diff --git a/server/service/grc/mock/mock.go b/server/service/grc/mock/mock.go
index 4a719058..53f5582d 100644
--- a/server/service/grc/mock/mock.go
+++ b/server/service/grc/mock/mock.go
@@ -37,16 +37,6 @@ type Distributor struct {
 
 const MatchGroup = "match-group"
 
-var PolicyNames = []string{
-       "retry",
-       "rateLimiting",
-       "circuitBreaker",
-       "instanceIsolation",
-       "faultInjection",
-       "bulkhead",
-       "loadbalance",
-}
-
 func (d *Distributor) Create(ctx context.Context, kind, project string, p 
*gov.Policy) ([]byte, error) {
        id, _ := uuid.NewV4()
        p.ID = id.String()
@@ -81,7 +71,7 @@ func (d *Distributor) Display(ctx context.Context, project, 
app, env string) ([]
        }
        policyMap := make(map[string]*gov.Policy)
        for _, g := range d.lbPolicies {
-               for _, kind := range PolicyNames {
+               for _, kind := range grcsvc.PolicyNames {
                        if checkPolicy(g, kind, app, env) {
                                policyMap[g.Name+kind] = g
                        }
@@ -90,7 +80,7 @@ func (d *Distributor) Display(ctx context.Context, project, 
app, env string) ([]
        r := make([]*gov.DisplayData, 0, len(list))
        for _, g := range list {
                policies := make([]*gov.Policy, 0)
-               for _, kind := range PolicyNames {
+               for _, kind := range grcsvc.PolicyNames {
                        policies = append(policies, policyMap[g.Name+kind])
                }
                r = append(r, &gov.DisplayData{
diff --git a/server/service/grc/policy.go b/server/service/grc/policy.go
index c22e6639..1caed373 100644
--- a/server/service/grc/policy.go
+++ b/server/service/grc/policy.go
@@ -19,7 +19,6 @@
 package grc
 
 import (
-       "errors"
        "fmt"
        "strings"
 
@@ -33,6 +32,8 @@ import (
 
 type ValueType string
 
+var PolicyNames []string
+
 // policySchemas saves policy kind and schema
 var policySchemas = make(map[string]*spec.Schema)
 
@@ -48,7 +49,7 @@ func ValidatePolicySpec(kind string, spec interface{}) error {
        schema, ok := policySchemas[kind]
        if !ok {
                log.Warn(fmt.Sprintf("can not recognize policy %s", kind))
-               return &ErrIllegalItem{"not support kind yet", kind}
+               return fmt.Errorf("not support kind[%s] yet", kind)
        }
        validator := validate.NewSchemaValidator(schema, nil, kind, 
strfmt.Default)
        errs := validator.Validate(spec).Errors
@@ -57,7 +58,7 @@ func ValidatePolicySpec(kind string, spec interface{}) error {
                for _, err := range errs {
                        str = append(str, err.Error())
                }
-               return errors.New(strings.Join(str, "; "))
+               return fmt.Errorf("illegal policy[%s] spec, msg: %s", kind, 
strings.Join(str, "; "))
        }
        return nil
 }
diff --git a/server/service/grc/validate.go b/server/service/grc/validate.go
index 26ed0870..06e39fd2 100644
--- a/server/service/grc/validate.go
+++ b/server/service/grc/validate.go
@@ -17,10 +17,6 @@
 
 package grc
 
-import (
-       "fmt"
-)
-
 const (
        KeyPrefix       = "servicecomb."
        KindMatchGroup  = "match-group"
@@ -31,12 +27,3 @@ const (
        KeyEnvironment  = "environment"
        EnvAll          = "all"
 )
-
-type ErrIllegalItem struct {
-       err string
-       val interface{}
-}
-
-func (e *ErrIllegalItem) Error() string {
-       return fmt.Sprintf("illegal item : %v , msg: %s", e.val, e.err)
-}
diff --git a/server/ext/policy/builtin_test.go 
b/server/service/grc/validate_test.go
similarity index 92%
rename from server/ext/policy/builtin_test.go
rename to server/service/grc/validate_test.go
index c0136edf..3db47f8a 100644
--- a/server/ext/policy/builtin_test.go
+++ b/server/service/grc/validate_test.go
@@ -15,14 +15,22 @@
  * limitations under the License.
  */
 
-package policy
+package grc_test
 
 import (
+       "os"
        "testing"
 
+       "github.com/apache/servicecomb-service-center/server/config"
        "github.com/apache/servicecomb-service-center/server/service/grc"
 )
 
+func init() {
+       os.Setenv("APP_ROOT", "./../../../etc/")
+       config.Init()
+       grc.Init()
+}
+
 func TestValidatePolicySpec(t *testing.T) {
        type args struct {
                kind string
@@ -68,14 +76,14 @@ func TestValidatePolicySpec(t *testing.T) {
                        map[string]interface{}{"name": "1", "apiPath": ""},
                }, "alias": "1"}}, true},
                {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
-                       map[string]interface{}{"name": "1", "apiPath": "1"},
+                       map[string]interface{}{"name": "1", "apiPath": 
map[string]interface{}{"prefix": "/"}},
                }, "alias": "1"}}, false},
                {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
-                       map[string]interface{}{"name": "1", "headers": ""},
+                       map[string]interface{}{"name": "1", "headers": nil},
                }, "alias": "1"}}, true},
                {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
                        map[string]interface{}{"name": "1", "headers": 
map[string]interface{}{}},
-               }, "alias": "1"}}, true},
+               }, "alias": "1"}}, false},
                {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
                        map[string]interface{}{"name": "1", "headers": 
map[string]interface{}{"k": "v"}},
                }, "alias": "1"}}, false},
@@ -98,10 +106,9 @@ func TestValidatePolicySpec(t *testing.T) {
 
                {kindRateLimiting, args{kind: kindRateLimiting, spec: ""}, 
true},
                {kindRateLimiting, args{kind: kindRateLimiting, spec: 
map[string]interface{}{}}, true},
-               {kindRateLimiting, args{kind: kindRateLimiting, spec: 
map[string]interface{}{"rate": -1}}, true},
                {kindRateLimiting, args{kind: kindRateLimiting, spec: 
map[string]interface{}{"rate": 1}}, false},
                {kindRateLimiting, args{kind: kindRateLimiting, spec: 
map[string]interface{}{"rate": 0.5}}, false},
-               {kindRateLimiting, args{kind: kindRateLimiting, spec: 
map[string]interface{}{"rate": "1"}}, true},
+               {kindRateLimiting, args{kind: kindRateLimiting, spec: 
map[string]interface{}{"rate": "1"}}, false},
 
                {kindLoadbalance, args{kind: kindLoadbalance, spec: ""}, true},
                {kindLoadbalance, args{kind: kindLoadbalance, spec: 
map[string]interface{}{}}, true},
@@ -117,9 +124,9 @@ func TestValidatePolicySpec(t *testing.T) {
 
                {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
""}, true},
                {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
map[string]interface{}{}}, true},
-               {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
map[string]interface{}{"minimumNumberOfCalls": -1}}, true},
+               {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
map[string]interface{}{"minimumNumberOfCalls": -1}}, false},
                {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
map[string]interface{}{"minimumNumberOfCalls": 1}}, false},
-               {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
map[string]interface{}{"minimumNumberOfCalls": "1"}}, true},
+               {kindInstanceIsolation, args{kind: kindInstanceIsolation, spec: 
map[string]interface{}{"minimumNumberOfCalls": "1"}}, false},
 
                {kindFaultInjection, args{kind: kindFaultInjection, spec: ""}, 
true},
                {kindFaultInjection, args{kind: kindFaultInjection, spec: 
map[string]interface{}{}}, true},
@@ -130,9 +137,9 @@ func TestValidatePolicySpec(t *testing.T) {
 
                {kindBulkhead, args{kind: kindBulkhead, spec: ""}, true},
                {kindBulkhead, args{kind: kindBulkhead, spec: 
map[string]interface{}{}}, true},
-               {kindBulkhead, args{kind: kindBulkhead, spec: 
map[string]interface{}{"maxConcurrentCalls": -1}}, true},
+               {kindBulkhead, args{kind: kindBulkhead, spec: 
map[string]interface{}{"maxConcurrentCalls": -1}}, false},
                {kindBulkhead, args{kind: kindBulkhead, spec: 
map[string]interface{}{"maxConcurrentCalls": 1}}, false},
-               {kindBulkhead, args{kind: kindBulkhead, spec: 
map[string]interface{}{"maxConcurrentCalls": "1"}}, true},
+               {kindBulkhead, args{kind: kindBulkhead, spec: 
map[string]interface{}{"maxConcurrentCalls": "1"}}, false},
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {

Reply via email to