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

commit e01d48593514c1cd571a479ceb2f5673b65e6ecd
Author: little-cui <[email protected]>
AuthorDate: Tue Aug 23 11:19:49 2022 +0800

    [fix]failed to create match-group policy (#1335)
    
    * [fix]failed to create match-group policy
    
    * [fix]failed to create match-group policy
---
 server/ext/policy/builtin.go      | 199 ++++++++++++++++++++++++++++++++++++++
 server/ext/policy/builtin_test.go | 144 +++++++++++++++++++++++++++
 server/ext/policy/buitin.go       |  68 -------------
 server/service/grc/policy.go      |  19 +---
 server/service/grc/validate.go    | 114 ----------------------
 5 files changed, 347 insertions(+), 197 deletions(-)

diff --git a/server/ext/policy/builtin.go b/server/ext/policy/builtin.go
new file mode 100644
index 00000000..b32c34ab
--- /dev/null
+++ b/server/ext/policy/builtin.go
@@ -0,0 +1,199 @@
+/*
+ * 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/ext/policy/builtin_test.go 
b/server/ext/policy/builtin_test.go
new file mode 100644
index 00000000..c0136edf
--- /dev/null
+++ b/server/ext/policy/builtin_test.go
@@ -0,0 +1,144 @@
+/*
+ * 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 (
+       "testing"
+
+       "github.com/apache/servicecomb-service-center/server/service/grc"
+)
+
+func TestValidatePolicySpec(t *testing.T) {
+       type args struct {
+               kind string
+               spec interface{}
+       }
+
+       kindMatchGroup := "match-group"
+       kindRetry := "retry"
+       kindRateLimiting := "rate-limiting"
+       kindLoadbalance := "loadbalance"
+       kindCircuitBreaker := "circuit-breaker"
+       kindInstanceIsolation := "instance-isolation"
+       kindFaultInjection := "fault-injection"
+       kindBulkhead := "bulkhead"
+
+       tests := []struct {
+               name    string
+               args    args
+               wantErr bool
+       }{
+               {"undefined", args{kind: "undefined", spec: 
map[string]interface{}{}}, true},
+
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: ""}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"": nil}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": nil}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{}}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{}, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{nil}, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{},
+               }, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": ""},
+               }, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1"},
+               }, "alias": "1"}}, false},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1"},
+               }, "alias": ""}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       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"},
+               }, "alias": "1"}}, false},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1", "headers": ""},
+               }, "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},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1", "headers": 
map[string]interface{}{"k": "v"}},
+               }, "alias": "1"}}, false},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1", "method": 
[]interface{}{}},
+               }, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1", "method": 
[]interface{}{1}},
+               }, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1", "method": 
[]interface{}{""}},
+               }, "alias": "1"}}, true},
+               {kindMatchGroup, args{kind: kindMatchGroup, spec: 
map[string]interface{}{"matches": []interface{}{
+                       map[string]interface{}{"name": "1", "method": 
[]interface{}{"GET"}},
+               }, "alias": "1"}}, false},
+
+               {kindRetry, args{kind: kindRetry, spec: ""}, true},
+               {kindRetry, args{kind: kindRetry, spec: 
map[string]interface{}{}}, true},
+               {kindRetry, args{kind: kindRetry, spec: 
map[string]interface{}{"maxAttempts": 3}}, false},
+
+               {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},
+
+               {kindLoadbalance, args{kind: kindLoadbalance, spec: ""}, true},
+               {kindLoadbalance, args{kind: kindLoadbalance, spec: 
map[string]interface{}{}}, true},
+               {kindLoadbalance, args{kind: kindLoadbalance, spec: 
map[string]interface{}{"rule": 1}}, true},
+               {kindLoadbalance, args{kind: kindLoadbalance, spec: 
map[string]interface{}{"rule": ""}}, true},
+               {kindLoadbalance, args{kind: kindLoadbalance, spec: 
map[string]interface{}{"rule": "1"}}, false},
+
+               {kindCircuitBreaker, args{kind: kindCircuitBreaker, spec: ""}, 
true},
+               {kindCircuitBreaker, args{kind: kindCircuitBreaker, spec: 
map[string]interface{}{}}, true},
+               {kindCircuitBreaker, args{kind: kindCircuitBreaker, spec: 
map[string]interface{}{"minimumNumberOfCalls": -1}}, true},
+               {kindCircuitBreaker, args{kind: kindCircuitBreaker, spec: 
map[string]interface{}{"minimumNumberOfCalls": 1}}, false},
+               {kindCircuitBreaker, args{kind: kindCircuitBreaker, spec: 
map[string]interface{}{"minimumNumberOfCalls": "1"}}, true},
+
+               {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"}}, true},
+
+               {kindFaultInjection, args{kind: kindFaultInjection, spec: ""}, 
true},
+               {kindFaultInjection, args{kind: kindFaultInjection, spec: 
map[string]interface{}{}}, true},
+               {kindFaultInjection, args{kind: kindFaultInjection, spec: 
map[string]interface{}{"percentage": -1}}, true},
+               {kindFaultInjection, args{kind: kindFaultInjection, spec: 
map[string]interface{}{"percentage": 1}}, false},
+               {kindFaultInjection, args{kind: kindFaultInjection, spec: 
map[string]interface{}{"percentage": 0.5}}, false},
+               {kindFaultInjection, args{kind: kindFaultInjection, spec: 
map[string]interface{}{"percentage": "1"}}, true},
+
+               {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"}}, true},
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if err := grc.ValidatePolicySpec(tt.args.kind, 
tt.args.spec); (err != nil) != tt.wantErr {
+                               t.Errorf("Validate() error = %v, wantErr %v", 
err, tt.wantErr)
+                       }
+               })
+       }
+}
diff --git a/server/ext/policy/buitin.go b/server/ext/policy/buitin.go
deleted file mode 100644
index 90e2e42e..00000000
--- a/server/ext/policy/buitin.go
+++ /dev/null
@@ -1,68 +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"
-)
-
-func init() {
-       grc.RegisterPolicySchema("loadbalance", &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type:     []string{"object"},
-                       Required: []string{"rule"},
-                       Properties: map[string]spec.Schema{
-                               "rule": {
-                                       SchemaProps: spec.SchemaProps{Type: 
[]string{"string"}}},
-                       },
-               }})
-       grc.RegisterPolicySchema("circuitBreaker", &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type: []string{"object"},
-                       Properties: map[string]spec.Schema{
-                               "minimumNumberOfCalls": {
-                                       SchemaProps: spec.SchemaProps{Type: 
[]string{"integer"}}},
-                       },
-               }})
-       grc.RegisterPolicySchema("instanceIsolation", &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type: []string{"object"},
-                       Properties: map[string]spec.Schema{
-                               "minimumNumberOfCalls": {
-                                       SchemaProps: spec.SchemaProps{Type: 
[]string{"integer"}}},
-                       },
-               }})
-       grc.RegisterPolicySchema("faultInjection", &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type: []string{"object"},
-                       Properties: map[string]spec.Schema{
-                               "percentage": {
-                                       SchemaProps: spec.SchemaProps{Type: 
[]string{"integer"}}},
-                       },
-               }})
-       grc.RegisterPolicySchema("bulkhead", &spec.Schema{
-               SchemaProps: spec.SchemaProps{
-                       Type: []string{"object"},
-                       Properties: map[string]spec.Schema{
-                               "maxConcurrentCalls": {
-                                       SchemaProps: spec.SchemaProps{Type: 
[]string{"integer"}}},
-                       },
-               }})
-
-}
diff --git a/server/service/grc/policy.go b/server/service/grc/policy.go
index a81ebf1f..c22e6639 100644
--- a/server/service/grc/policy.go
+++ b/server/service/grc/policy.go
@@ -44,31 +44,20 @@ func RegisterPolicySchema(kind string, schema *spec.Schema) 
{
 }
 
 // ValidatePolicySpec validates spec attributes
-// it first us legacy mechanism Validate 3 kinds of policy.
-// then it use new mechanism to validate all of other policy
 func ValidatePolicySpec(kind string, spec interface{}) error {
-       // TODO this legacy API should be removed. after 3 kinds of policy 
schema is registered by "RegisterPolicySchema"
-       err := Validate(kind, spec)
-       if err != nil {
-               return err
-       }
        schema, ok := policySchemas[kind]
        if !ok {
                log.Warn(fmt.Sprintf("can not recognize policy %s", kind))
                return &ErrIllegalItem{"not support kind yet", kind}
        }
-       validator := validate.NewSchemaValidator(schema, nil, "", 
strfmt.Default)
+       validator := validate.NewSchemaValidator(schema, nil, kind, 
strfmt.Default)
        errs := validator.Validate(spec).Errors
        if len(errs) != 0 {
                var str []string
-               for i, err := range errs {
-                       if i != 0 {
-                               str = append(str, ";", err.Error())
-                       } else {
-                               str = append(str, err.Error())
-                       }
+               for _, err := range errs {
+                       str = append(str, err.Error())
                }
-               return errors.New(strings.Join(str, ";"))
+               return errors.New(strings.Join(str, "; "))
        }
        return nil
 }
diff --git a/server/service/grc/validate.go b/server/service/grc/validate.go
index f19c40df..26ed0870 100644
--- a/server/service/grc/validate.go
+++ b/server/service/grc/validate.go
@@ -30,10 +30,6 @@ const (
        KeyApp          = "app"
        KeyEnvironment  = "environment"
        EnvAll          = "all"
-       Alias           = "alias"
-       Method          = "method"
-       Matches         = "matches"
-       Rules           = "rules"
 )
 
 type ErrIllegalItem struct {
@@ -41,116 +37,6 @@ type ErrIllegalItem struct {
        val interface{}
 }
 
-var (
-       methodSet map[string]bool
-)
-
 func (e *ErrIllegalItem) Error() string {
        return fmt.Sprintf("illegal item : %v , msg: %s", e.val, e.err)
 }
-
-// Validate is a legacy API, it is not extensible due to its bad design pattern
-// Please use grc.RegisterPolicySchema
-// it only response for validate 3 kinds of policy. if it is not this 3 kinds, 
it will not return error,
-// it return nil error, and let grc.ValidatePolicySpec to do the job
-func Validate(kind string, spec interface{}) error {
-       switch kind {
-       case "match-group":
-               return matchValidate(spec)
-       case "retry":
-               return retryValidate(spec)
-       case "rate-limiting":
-               return rateLimitingValidate(spec)
-       default:
-               return nil
-       }
-}
-
-func matchValidate(val interface{}) error {
-       spec, ok := val.(map[string]interface{})
-       if !ok {
-               return &ErrIllegalItem{"can not cast to map", val}
-       }
-       if spec[Matches] == nil {
-               return nil
-       }
-       alias, ok := spec[Alias].(string)
-       if !ok {
-               return &ErrIllegalItem{"alias must be string", alias}
-       }
-       matches, ok := spec[Matches].([]interface{})
-       if !ok {
-               return &ErrIllegalItem{"don't have matches", spec}
-       }
-       for _, match := range matches {
-               match, ok := match.(map[string]interface{})
-               if !ok {
-                       return &ErrIllegalItem{"match can not cast to map", 
match}
-               }
-               if match["name"] == nil {
-                       return &ErrIllegalItem{"match's name can not be null", 
match}
-               }
-               if match["apiPath"] == nil && match["headers"] == nil && 
match[Method] == nil {
-                       return &ErrIllegalItem{"match must have a match item 
[apiPath/headers/methods]", match}
-               }
-               //apiPath & headers do not check
-               if match[Method] != nil {
-                       methods, ok := match[Method].([]interface{})
-                       if !ok {
-                               return &ErrIllegalItem{"methods must be a 
list", match}
-                       }
-                       for _, method := range methods {
-                               methodStr, ok := method.(string)
-                               if !ok {
-                                       return &ErrIllegalItem{"method must be 
a string", method}
-                               }
-                               if !methodSet[methodStr] {
-                                       return &ErrIllegalItem{"method must be 
one of the GET/POST/PUT/DELETE/PATCH", method}
-                               }
-                       }
-               }
-       }
-       return nil
-}
-
-func retryValidate(val interface{}) error {
-       err := policyValidate(val)
-       if err != nil {
-               return err
-       }
-       return nil
-}
-
-func rateLimitingValidate(val interface{}) error {
-       err := policyValidate(val)
-       if err != nil {
-               return err
-       }
-       return nil
-}
-
-func policyValidate(val interface{}) error {
-       spec, ok := val.(map[string]interface{})
-       if !ok {
-               return &ErrIllegalItem{"policy can not cast to map", val}
-       }
-       if spec[Rules] != nil {
-               rules, ok := spec[Rules].(map[string]interface{})
-               if !ok {
-                       return &ErrIllegalItem{"policy's rules can not cast to 
map", spec}
-               }
-               if "" == rules["match"] {
-                       return &ErrIllegalItem{"policy's rules match can not be 
nil", spec}
-               }
-       }
-       return nil
-}
-
-func init() {
-       methodSet = make(map[string]bool)
-       methodSet["GET"] = true
-       methodSet["POST"] = true
-       methodSet["DELETE"] = true
-       methodSet["PUT"] = true
-       methodSet["PATCH"] = true
-}

Reply via email to