You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/10/16 09:25:26 UTC

[apisix-dashboard] 01/01: feat: sync apis

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

juzhiyuan pushed a commit to branch feat-fe-refactor-sync
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git

commit 1819a2e3c98c6343476ab2918570155c4404fbe4
Merge: 43af140 061d9a2
Author: juzhiyuan <ju...@apache.org>
AuthorDate: Fri Oct 16 17:25:03 2020 +0800

    feat: sync apis

 .actions/ASF-Release.cfg                           |    5 +
 .github/workflows/api_ci.yml                       |   82 +-
 .github/workflows/api_cicd.yml                     |   32 +-
 api/Dockerfile                                     |   14 +
 api/build-tools/json.lua                           |  400 ++++
 api/build-tools/schema-sync.lua                    |  133 ++
 api/conf/conf.go                                   |   65 +-
 api/conf/schema.json                               | 2203 ++++++++++++++++++++
 api/errno/error.go                                 |  170 --
 api/filter/authentication.go                       |   32 +-
 api/filter/logging.go                              |    5 +-
 api/filter/request_id.go                           |    1 +
 api/go.mod                                         |   22 +-
 api/go.sum                                         |  402 +++-
 api/internal/core/entity/entity.go                 |  182 ++
 api/internal/core/entity/query.go                  |  153 ++
 api/internal/core/storage/etcd.go                  |  138 ++
 .../copy.go => internal/core/storage/storage.go}   |   44 +-
 api/internal/core/storage/storage_mock.go          |  116 ++
 api/internal/core/store/query.go                   |  151 ++
 api/internal/core/store/selector.go                |  144 ++
 api/internal/core/store/selector_test.go           |  285 +++
 api/internal/core/store/store.go                   |  326 +++
 api/internal/core/store/store_test.go              |  763 +++++++
 api/internal/core/store/storehub.go                |  145 ++
 api/internal/core/store/test_case.json             |   19 +
 api/internal/core/store/validate.go                |  155 ++
 api/internal/core/store/validate_mock.go           |   24 +
 api/internal/core/store/validate_test.go           |  140 ++
 .../handler/authentication/authentication.go       |   78 +
 .../handler/authentication/authentication_test.go  |   67 +
 api/internal/handler/consumer/consumer.go          |  149 ++
 api/internal/handler/consumer/consumer_test.go     |  200 ++
 .../base_test.go => internal/handler/handler.go}   |   10 +-
 api/{route => internal/handler/healthz}/healthz.go |   28 +-
 api/internal/handler/plugin/plugin.go              |   65 +
 .../handler/plugin/plugin_test.go}                 |   47 +-
 api/internal/handler/route/route.go                |  345 +++
 api/internal/handler/route/route_test.go           |  847 ++++++++
 api/internal/handler/service/service.go            |  175 ++
 api/internal/handler/service/service_test.go       |  152 ++
 api/internal/handler/ssl/ssl.go                    |  373 ++++
 api/{route => internal/handler/ssl}/ssl_test.go    |  132 +-
 api/internal/handler/upstream/upstream.go          |  252 +++
 api/internal/handler/upstream/upstream_test.go     |  183 ++
 api/{route/base.go => internal/route.go}           |   39 +-
 api/{route/healthz.go => internal/utils/closer.go} |   27 +-
 .../utils/consts/api_error.go}                     |   38 +-
 .../utils/consts/error.go}                         |   25 +-
 api/internal/utils/utils.go                        |   79 +
 .../base_test.go => internal/utils/utils_test.go}  |   29 +-
 api/log/log.go                                     |   55 +
 api/main.go                                        |   28 +-
 api/route/authentication.go                        |   68 -
 api/route/authentication_test.go                   |   52 -
 api/route/consumer.go                              |  143 --
 api/route/consumer_test.go                         |   98 -
 api/route/plugin.go                                |   59 -
 api/route/route.go                                 |  631 ------
 api/route/route_group.go                           |  233 ---
 api/route/route_group_test.go                      |  131 --
 api/route/route_test.go                            |  229 --
 api/route/ssl.go                                   |  197 --
 api/route/upstream.go                              |  384 ----
 api/script/db/schema.sql                           |   71 -
 api/service/base.go                                |   49 -
 api/service/consumer.go                            |  349 ----
 api/service/consumer_test.go                       |  133 --
 api/service/plugin.go                              |   62 -
 api/service/route.go                               |  652 ------
 api/service/route_group.go                         |  155 --
 api/service/route_group_test.go                    |  120 --
 api/service/route_test.go                          |  329 ---
 api/service/ssl.go                                 |  589 ------
 api/service/ssl_test.go                            |  352 ----
 api/service/upstream.go                            |  271 ---
 api/service/upstream_test.go                       |  108 -
 api/utils/http.go                                  |  114 -
 78 files changed, 9348 insertions(+), 6005 deletions(-)

diff --cc .github/workflows/api_ci.yml
index b17e583,907e0e6..3a380bd
--- a/.github/workflows/api_ci.yml
+++ b/.github/workflows/api_ci.yml
@@@ -7,9 -8,12 +8,10 @@@ on
    pull_request:
      branches:
        - master
+       - refactor
  
  jobs:
 -
    run-test:
 -
      runs-on: ubuntu-latest
  
      services:
diff --cc .github/workflows/api_cicd.yml
index 13494fe,481c8cc..74aaa50
--- a/.github/workflows/api_cicd.yml
+++ b/.github/workflows/api_cicd.yml
@@@ -23,54 -23,65 +23,64 @@@ jobs
          env:
            MYSQL_ROOT_PASSWORD: 123456
          ports:
 -            - '3306:3306'
 +          - '3306:3306'
          options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
  
 -
      steps:
 -    - uses: actions/checkout@v2
 -    
 -    - name: run apisix
 -      run: |
 -        network=$(docker network ls | grep github_network | awk '{print $2}')
 -        docker run --name apisix  -d -p 9080:9080 \
 -        -v ${{ github.workspace }}/.github/apisix-config.yaml:/usr/local/apisix/conf/config.yaml \
 -        --network "$network" --network-alias apisix \
 -        apache/apisix:dev
 -        sleep 5
 -        docker logs apisix
 +      - uses: actions/checkout@v2
  
 -    - name: setting up database
 -      run: |
 -        mysql -h 127.0.0.1 --port 3306 -u root -p123456  < ./api/script/db/schema.sql
 +      - name: run apisix
 +        run: |
 +          network=$(docker network ls | grep github_network | awk '{print $2}')
 +          docker run --name apisix  -d -p 9080:9080 \
 +          -v ${{ github.workspace }}/.github/apisix-config.yaml:/usr/local/apisix/conf/config.yaml \
 +          --network "$network" --network-alias apisix \
 +          apache/apisix:dev
 +          sleep 5
 +          docker logs apisix
  
 -    - name: ping apisix
 -      run: |
 -        curl 127.0.0.1:9080
 +      - name: setting up database
 +        run: |
 +          mysql -h 127.0.0.1 --port 3306 -u root -p123456  < ./api/script/db/schema.sql
 +
 +      - name: ping apisix
 +        run: |
 +          curl 127.0.0.1:9080
  
-       - name: get lua lib
-         run: |
-           wget https://github.com/api7/dag-to-lua/archive/v1.1.tar.gz
-           sudo mkdir -p /go/api7-manager-api/dag-to-lua/
-           tar -zxvf v1.1.tar.gz
-           sudo mv ./dag-to-lua-1.1/lib/* /go/api7-manager-api/dag-to-lua/
+     - name: get lua lib
+       run: |
+         wget https://github.com/api7/dag-to-lua/archive/v1.1.tar.gz
+         sudo mkdir -p /go/manager-api/dag-to-lua/
+         tar -zxvf v1.1.tar.gz
+         sudo mv ./dag-to-lua-1.1/lib/* /go/manager-api/dag-to-lua/
  
 -    - name: install runtime
 -      run: |
 -        sudo apt-get update
 -        sudo apt-get install lua5.1
 -        sudo add-apt-repository ppa:longsleep/golang-backports
 -        sudo apt update
 -        export GO111MOUDULE=on
 -        sudo apt install golang-1.14-go
 +      - name: install runtime
 +        run: |
 +          sudo apt-get update
 +          sudo apt-get install lua5.1
 +          sudo add-apt-repository ppa:longsleep/golang-backports
 +          sudo apt update
 +          export GO111MOUDULE=on
 +          sudo apt install golang-1.14-go
  
-       - uses: Azure/docker-login@v1
-         with:
-           login-server: apisixacr.azurecr.cn
-           username: ${{ secrets.REGISTRY_USERNAME }}
-           password: ${{ secrets.REGISTRY_PASSWORD }}
+     - name: generate json schema
+       working-directory: ./api
+       run: |
+         wget https://github.com/apache/apisix/archive/master.zip
+         mkdir ./build-tools/apisix/
+         unzip master.zip
+         sudo mv ./apisix-master/apisix/* ./build-tools/apisix/
+         rm -rf ./apisix-master
+         cd ./build-tools/ && lua schema-sync.lua > ../conf/schema.json
+ 
+     - uses: Azure/docker-login@v1
+       with:
+         login-server: apisixacr.azurecr.cn
+         username: ${{ secrets.REGISTRY_USERNAME }}
+         password: ${{ secrets.REGISTRY_PASSWORD }}
  
 -    - name: build and push docker image   
 -      run: |
 -        cd ./api
 -        docker build . -t apisixacr.azurecr.cn/managerapi:${{ github.sha }}
 -        docker push apisixacr.azurecr.cn/managerapi:${{ github.sha }}
 +      - name: build and push docker image
 +        run: |
 +          cd ./api
 +          docker build . -t apisixacr.azurecr.cn/managerapi:${{ github.sha }}
 +          docker push apisixacr.azurecr.cn/managerapi:${{ github.sha }}
diff --cc api/conf/schema.json
index 0000000,087cf4c..861942a
mode 000000,100644..100644
--- a/api/conf/schema.json
+++ b/api/conf/schema.json
@@@ -1,0 -1,1 +1,2203 @@@
 -{"main":{"upstream_hash_header_schema":{"type":"string","pattern":"^[a-zA-Z0-9-_]+$"},"stream_route":{"type":"object","properties":{"plugins":{"type":"object"},"id":{"anyOf":[{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9-_]+$"},{"type":"integer","minimum":1}]},"remote_addr":{"type":"string","anyOf":[{"title":"IPv4","type":"string","pattern":"^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"},{"title":"IPv4/CIDR","type":"string","pattern":"^[0-9]{1,3}.[0-9]{1,3}.[0-9] [...]
++{
++  "main": {
++    "upstream_hash_header_schema": { "type": "string", "pattern": "^[a-zA-Z0-9-_]+$" },
++    "stream_route": {
++      "type": "object",
++      "properties": {
++        "plugins": { "type": "object" },
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "remote_addr": {
++          "type": "string",
++          "anyOf": [
++            {
++              "title": "IPv4",
++              "type": "string",
++              "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++            },
++            {
++              "title": "IPv4/CIDR",
++              "type": "string",
++              "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++            },
++            {
++              "title": "IPv6",
++              "type": "string",
++              "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++            },
++            {
++              "title": "IPv6/CIDR",
++              "type": "string",
++              "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++            }
++          ],
++          "description": "client IP"
++        },
++        "upstream_id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "upstream": {
++          "type": "object",
++          "additionalProperties": false,
++          "properties": {
++            "create_time": { "type": "integer" },
++            "hash_on": {
++              "type": "string",
++              "enum": ["vars", "header", "cookie", "consumer"],
++              "default": "vars"
++            },
++            "pass_host": {
++              "type": "string",
++              "default": "pass",
++              "enum": ["pass", "node", "rewrite"],
++              "description": "mod of host passing"
++            },
++            "type": {
++              "type": "string",
++              "enum": ["chash", "roundrobin", "ewma"],
++              "description": "algorithms of load balancing"
++            },
++            "enable_websocket": {
++              "type": "boolean",
++              "description": "enable websocket for request"
++            },
++            "update_time": { "type": "integer" },
++            "labels": {
++              "type": "object",
++              "maxProperties": 16,
++              "patternProperties": {
++                ".*": {
++                  "type": "string",
++                  "maxLength": 64,
++                  "minLength": 1,
++                  "pattern": "^[a-zA-Z0-9-_.]+$",
++                  "description": "value of label"
++                }
++              },
++              "description": "key/value pairs to specify attributes"
++            },
++            "retries": { "type": "integer", "minimum": 0 },
++            "service_name": { "type": "string", "maxLength": 50 },
++            "id": {
++              "anyOf": [
++                {
++                  "type": "string",
++                  "minLength": 1,
++                  "maxLength": 64,
++                  "pattern": "^[a-zA-Z0-9-_]+$"
++                },
++                { "type": "integer", "minimum": 1 }
++              ]
++            },
++            "key": {
++              "type": "string",
++              "description": "the key of chash for dynamic load balancing"
++            },
++            "name": { "type": "string", "maxLength": 50 },
++            "upstream_host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++            "timeout": {
++              "type": "object",
++              "properties": {
++                "send": { "type": "number", "minimum": 0 },
++                "read": { "type": "number", "minimum": 0 },
++                "connect": { "type": "number", "minimum": 0 }
++              },
++              "required": ["connect", "send", "read"]
++            },
++            "k8s_deployment_info": {
++              "type": "object",
++              "properties": {
++                "port": { "type": "number", "minimum": 0 },
++                "deploy_name": { "type": "string", "description": "k8s deployment name" },
++                "service_name": { "type": "string", "description": "k8s service name" },
++                "namespace": { "type": "string", "description": "k8s namespace" },
++                "backend_type": {
++                  "type": "string",
++                  "description": "k8s service name",
++                  "enum": ["svc", "pod"],
++                  "default": "pod"
++                }
++              },
++              "anyOf": [
++                { "required": ["namespace", "deploy_name", "port"] },
++                { "required": ["namespace", "service_name", "port"] }
++              ]
++            },
++            "desc": { "type": "string", "maxLength": 256 },
++            "checks": {
++              "type": "object",
++              "anyOf": [{ "required": ["active"] }, { "required": ["active", "passive"] }],
++              "properties": {
++                "active": {
++                  "type": "object",
++                  "properties": {
++                    "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                    "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
++                    "http_path": { "type": "string", "default": "/" },
++                    "req_headers": {
++                      "type": "array",
++                      "items": { "type": "string", "uniqueItems": true },
++                      "minItems": 1
++                    },
++                    "type": {
++                      "type": "string",
++                      "enum": ["http", "https", "tcp"],
++                      "default": "http"
++                    },
++                    "timeout": { "type": "number", "default": 1 },
++                    "concurrency": { "type": "integer", "default": 10 },
++                    "healthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [200, 302],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                        "successes": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "unhealthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_failures": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [429, 404, 500, 501, 502, 503, 504, 505],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                        "timeouts": {
++                          "type": "integer",
++                          "default": 3,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "tcp_failures": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "https_verify_certificate": { "type": "boolean", "default": true }
++                  }
++                },
++                "passive": {
++                  "type": "object",
++                  "properties": {
++                    "type": {
++                      "type": "string",
++                      "enum": ["http", "https", "tcp"],
++                      "default": "http"
++                    },
++                    "unhealthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [429, 500, 503],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "timeouts": {
++                          "type": "integer",
++                          "default": 7,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "http_failures": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "tcp_failures": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "healthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [
++                            200,
++                            201,
++                            202,
++                            203,
++                            204,
++                            205,
++                            206,
++                            207,
++                            208,
++                            226,
++                            300,
++                            301,
++                            302,
++                            303,
++                            304,
++                            305,
++                            306,
++                            307,
++                            308
++                          ],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "successes": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    }
++                  }
++                }
++              },
++              "additionalProperties": false
++            },
++            "nodes": {
++              "anyOf": [
++                {
++                  "type": "object",
++                  "patternProperties": {
++                    ".*": { "type": "integer", "minimum": 0, "description": "weight of node" }
++                  },
++                  "minProperties": 1
++                },
++                {
++                  "type": "array",
++                  "items": {
++                    "type": "object",
++                    "properties": {
++                      "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                      "port": { "type": "integer", "minimum": 1, "description": "port of node" },
++                      "weight": {
++                        "type": "integer",
++                        "minimum": 0,
++                        "description": "weight of node"
++                      },
++                      "metadata": { "type": "object", "description": "metadata of node" }
++                    },
++                    "required": ["host", "port", "weight"]
++                  },
++                  "minItems": 1
++                }
++              ]
++            }
++          },
++          "anyOf": [
++            { "required": ["type", "nodes"] },
++            { "required": ["type", "k8s_deployment_info"] },
++            { "required": ["type", "service_name"] }
++          ]
++        },
++        "server_addr": {
++          "type": "string",
++          "anyOf": [
++            {
++              "title": "IPv4",
++              "type": "string",
++              "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++            },
++            {
++              "title": "IPv4/CIDR",
++              "type": "string",
++              "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++            },
++            {
++              "title": "IPv6",
++              "type": "string",
++              "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++            },
++            {
++              "title": "IPv6/CIDR",
++              "type": "string",
++              "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++            }
++          ],
++          "description": "server IP"
++        },
++        "server_port": { "type": "integer", "description": "server port" }
++      }
++    },
++    "label_value_def": {
++      "type": "string",
++      "maxLength": 64,
++      "minLength": 1,
++      "pattern": "^[a-zA-Z0-9-_.]+$",
++      "description": "value of label"
++    },
++    "consumer": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "update_time": { "type": "integer" },
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "create_time": { "type": "integer" },
++        "plugins": { "type": "object" },
++        "desc": { "type": "string", "maxLength": 256 },
++        "username": {
++          "type": "string",
++          "minLength": 1,
++          "maxLength": 32,
++          "pattern": "^[a-zA-Z0-9_]+$"
++        },
++        "labels": {
++          "type": "object",
++          "maxProperties": 16,
++          "patternProperties": {
++            ".*": {
++              "type": "string",
++              "maxLength": 64,
++              "minLength": 1,
++              "pattern": "^[a-zA-Z0-9-_.]+$",
++              "description": "value of label"
++            }
++          },
++          "description": "key/value pairs to specify attributes"
++        }
++      },
++      "required": ["username"]
++    },
++    "proto": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": { "content": { "type": "string", "minLength": 1, "maxLength": 1048576 } },
++      "required": ["content"]
++    },
++    "version": 0.5,
++    "upstream_hash_vars_schema": {
++      "type": "string",
++      "pattern": "^((uri|server_name|server_addr|request_uri|remote_port|remote_addr|query_string|host|hostname)|arg_[0-9a-zA-z_-]+)$"
++    },
++    "global_rule": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "plugins": { "type": "object" }
++      },
++      "required": ["plugins"]
++    },
++    "ip_def": [
++      {
++        "title": "IPv4",
++        "type": "string",
++        "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++      },
++      {
++        "title": "IPv4/CIDR",
++        "type": "string",
++        "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++      },
++      {
++        "title": "IPv6",
++        "type": "string",
++        "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++      },
++      {
++        "title": "IPv6/CIDR",
++        "type": "string",
++        "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++      }
++    ],
++    "id_schema": {
++      "anyOf": [
++        { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++        { "type": "integer", "minimum": 1 }
++      ]
++    },
++    "host_def": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++    "service": {
++      "type": "object",
++      "properties": {
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "create_time": { "type": "integer" },
++        "upstream_id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "script": { "type": "string", "minLength": 10, "maxLength": 102400 },
++        "name": { "type": "string", "maxLength": 50 },
++        "update_time": { "type": "integer" },
++        "upstream": {
++          "type": "object",
++          "additionalProperties": false,
++          "properties": {
++            "create_time": { "type": "integer" },
++            "hash_on": {
++              "type": "string",
++              "enum": ["vars", "header", "cookie", "consumer"],
++              "default": "vars"
++            },
++            "pass_host": {
++              "type": "string",
++              "default": "pass",
++              "enum": ["pass", "node", "rewrite"],
++              "description": "mod of host passing"
++            },
++            "type": {
++              "type": "string",
++              "enum": ["chash", "roundrobin", "ewma"],
++              "description": "algorithms of load balancing"
++            },
++            "enable_websocket": {
++              "type": "boolean",
++              "description": "enable websocket for request"
++            },
++            "update_time": { "type": "integer" },
++            "labels": {
++              "type": "object",
++              "maxProperties": 16,
++              "patternProperties": {
++                ".*": {
++                  "type": "string",
++                  "maxLength": 64,
++                  "minLength": 1,
++                  "pattern": "^[a-zA-Z0-9-_.]+$",
++                  "description": "value of label"
++                }
++              },
++              "description": "key/value pairs to specify attributes"
++            },
++            "retries": { "type": "integer", "minimum": 0 },
++            "service_name": { "type": "string", "maxLength": 50 },
++            "id": {
++              "anyOf": [
++                {
++                  "type": "string",
++                  "minLength": 1,
++                  "maxLength": 64,
++                  "pattern": "^[a-zA-Z0-9-_]+$"
++                },
++                { "type": "integer", "minimum": 1 }
++              ]
++            },
++            "key": {
++              "type": "string",
++              "description": "the key of chash for dynamic load balancing"
++            },
++            "name": { "type": "string", "maxLength": 50 },
++            "upstream_host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++            "timeout": {
++              "type": "object",
++              "properties": {
++                "send": { "type": "number", "minimum": 0 },
++                "read": { "type": "number", "minimum": 0 },
++                "connect": { "type": "number", "minimum": 0 }
++              },
++              "required": ["connect", "send", "read"]
++            },
++            "k8s_deployment_info": {
++              "type": "object",
++              "properties": {
++                "port": { "type": "number", "minimum": 0 },
++                "deploy_name": { "type": "string", "description": "k8s deployment name" },
++                "service_name": { "type": "string", "description": "k8s service name" },
++                "namespace": { "type": "string", "description": "k8s namespace" },
++                "backend_type": {
++                  "type": "string",
++                  "description": "k8s service name",
++                  "enum": ["svc", "pod"],
++                  "default": "pod"
++                }
++              },
++              "anyOf": [
++                { "required": ["namespace", "deploy_name", "port"] },
++                { "required": ["namespace", "service_name", "port"] }
++              ]
++            },
++            "desc": { "type": "string", "maxLength": 256 },
++            "checks": {
++              "type": "object",
++              "anyOf": [{ "required": ["active"] }, { "required": ["active", "passive"] }],
++              "properties": {
++                "active": {
++                  "type": "object",
++                  "properties": {
++                    "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                    "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
++                    "http_path": { "type": "string", "default": "/" },
++                    "req_headers": {
++                      "type": "array",
++                      "items": { "type": "string", "uniqueItems": true },
++                      "minItems": 1
++                    },
++                    "type": {
++                      "type": "string",
++                      "enum": ["http", "https", "tcp"],
++                      "default": "http"
++                    },
++                    "timeout": { "type": "number", "default": 1 },
++                    "concurrency": { "type": "integer", "default": 10 },
++                    "healthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [200, 302],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                        "successes": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "unhealthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_failures": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [429, 404, 500, 501, 502, 503, 504, 505],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                        "timeouts": {
++                          "type": "integer",
++                          "default": 3,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "tcp_failures": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "https_verify_certificate": { "type": "boolean", "default": true }
++                  }
++                },
++                "passive": {
++                  "type": "object",
++                  "properties": {
++                    "type": {
++                      "type": "string",
++                      "enum": ["http", "https", "tcp"],
++                      "default": "http"
++                    },
++                    "unhealthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [429, 500, 503],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "timeouts": {
++                          "type": "integer",
++                          "default": 7,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "http_failures": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "tcp_failures": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "healthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [
++                            200,
++                            201,
++                            202,
++                            203,
++                            204,
++                            205,
++                            206,
++                            207,
++                            208,
++                            226,
++                            300,
++                            301,
++                            302,
++                            303,
++                            304,
++                            305,
++                            306,
++                            307,
++                            308
++                          ],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "successes": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    }
++                  }
++                }
++              },
++              "additionalProperties": false
++            },
++            "nodes": {
++              "anyOf": [
++                {
++                  "type": "object",
++                  "patternProperties": {
++                    ".*": { "type": "integer", "minimum": 0, "description": "weight of node" }
++                  },
++                  "minProperties": 1
++                },
++                {
++                  "type": "array",
++                  "items": {
++                    "type": "object",
++                    "properties": {
++                      "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                      "port": { "type": "integer", "minimum": 1, "description": "port of node" },
++                      "weight": {
++                        "type": "integer",
++                        "minimum": 0,
++                        "description": "weight of node"
++                      },
++                      "metadata": { "type": "object", "description": "metadata of node" }
++                    },
++                    "required": ["host", "port", "weight"]
++                  },
++                  "minItems": 1
++                }
++              ]
++            }
++          },
++          "anyOf": [
++            { "required": ["type", "nodes"] },
++            { "required": ["type", "k8s_deployment_info"] },
++            { "required": ["type", "service_name"] }
++          ]
++        },
++        "desc": { "type": "string", "maxLength": 256 },
++        "plugins": { "type": "object" },
++        "labels": {
++          "type": "object",
++          "maxProperties": 16,
++          "patternProperties": {
++            ".*": {
++              "type": "string",
++              "maxLength": 64,
++              "minLength": 1,
++              "pattern": "^[a-zA-Z0-9-_.]+$",
++              "description": "value of label"
++            }
++          },
++          "description": "key/value pairs to specify attributes"
++        }
++      },
++      "additionalProperties": false
++    },
++    "plugin_disable_schema": { "disable": { "type": "boolean" } },
++    "ssl": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "cert": { "type": "string", "minLength": 128, "maxLength": 65536 },
++        "keys": {
++          "type": "array",
++          "items": { "type": "string", "minLength": 128, "maxLength": 65536 }
++        },
++        "validity_end": { "type": "integer" },
++        "exptime": { "type": "integer", "minimum": 1588262400 },
++        "sni": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++        "key": { "type": "string", "minLength": 128, "maxLength": 65536 },
++        "snis": {
++          "type": "array",
++          "items": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" }
++        },
++        "create_time": { "type": "integer" },
++        "update_time": { "type": "integer" },
++        "status": {
++          "type": "integer",
++          "default": 1,
++          "enum": [1, 0],
++          "description": "ssl status, 1 to enable, 0 to disable"
++        },
++        "validity_start": { "type": "integer" },
++        "certs": {
++          "type": "array",
++          "items": { "type": "string", "minLength": 128, "maxLength": 65536 }
++        },
++        "labels": {
++          "type": "object",
++          "maxProperties": 16,
++          "patternProperties": {
++            ".*": {
++              "type": "string",
++              "maxLength": 64,
++              "minLength": 1,
++              "pattern": "^[a-zA-Z0-9-_.]+$",
++              "description": "value of label"
++            }
++          },
++          "description": "key/value pairs to specify attributes"
++        }
++      },
++      "oneOf": [{ "required": ["sni", "key", "cert"] }, { "required": ["snis", "key", "cert"] }]
++    },
++    "upstream": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "create_time": { "type": "integer" },
++        "hash_on": {
++          "type": "string",
++          "enum": ["vars", "header", "cookie", "consumer"],
++          "default": "vars"
++        },
++        "pass_host": {
++          "type": "string",
++          "default": "pass",
++          "enum": ["pass", "node", "rewrite"],
++          "description": "mod of host passing"
++        },
++        "type": {
++          "type": "string",
++          "enum": ["chash", "roundrobin", "ewma"],
++          "description": "algorithms of load balancing"
++        },
++        "enable_websocket": { "type": "boolean", "description": "enable websocket for request" },
++        "update_time": { "type": "integer" },
++        "labels": {
++          "type": "object",
++          "maxProperties": 16,
++          "patternProperties": {
++            ".*": {
++              "type": "string",
++              "maxLength": 64,
++              "minLength": 1,
++              "pattern": "^[a-zA-Z0-9-_.]+$",
++              "description": "value of label"
++            }
++          },
++          "description": "key/value pairs to specify attributes"
++        },
++        "retries": { "type": "integer", "minimum": 0 },
++        "service_name": { "type": "string", "maxLength": 50 },
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "key": { "type": "string", "description": "the key of chash for dynamic load balancing" },
++        "name": { "type": "string", "maxLength": 50 },
++        "upstream_host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++        "timeout": {
++          "type": "object",
++          "properties": {
++            "send": { "type": "number", "minimum": 0 },
++            "read": { "type": "number", "minimum": 0 },
++            "connect": { "type": "number", "minimum": 0 }
++          },
++          "required": ["connect", "send", "read"]
++        },
++        "k8s_deployment_info": {
++          "type": "object",
++          "properties": {
++            "port": { "type": "number", "minimum": 0 },
++            "deploy_name": { "type": "string", "description": "k8s deployment name" },
++            "service_name": { "type": "string", "description": "k8s service name" },
++            "namespace": { "type": "string", "description": "k8s namespace" },
++            "backend_type": {
++              "type": "string",
++              "description": "k8s service name",
++              "enum": ["svc", "pod"],
++              "default": "pod"
++            }
++          },
++          "anyOf": [
++            { "required": ["namespace", "deploy_name", "port"] },
++            { "required": ["namespace", "service_name", "port"] }
++          ]
++        },
++        "desc": { "type": "string", "maxLength": 256 },
++        "checks": {
++          "type": "object",
++          "anyOf": [{ "required": ["active"] }, { "required": ["active", "passive"] }],
++          "properties": {
++            "active": {
++              "type": "object",
++              "properties": {
++                "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
++                "http_path": { "type": "string", "default": "/" },
++                "req_headers": {
++                  "type": "array",
++                  "items": { "type": "string", "uniqueItems": true },
++                  "minItems": 1
++                },
++                "type": { "type": "string", "enum": ["http", "https", "tcp"], "default": "http" },
++                "timeout": { "type": "number", "default": 1 },
++                "concurrency": { "type": "integer", "default": 10 },
++                "healthy": {
++                  "type": "object",
++                  "properties": {
++                    "http_statuses": {
++                      "type": "array",
++                      "uniqueItems": true,
++                      "default": [200, 302],
++                      "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                      "minItems": 1
++                    },
++                    "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                    "successes": { "type": "integer", "default": 2, "minimum": 1, "maximum": 254 }
++                  }
++                },
++                "unhealthy": {
++                  "type": "object",
++                  "properties": {
++                    "http_failures": {
++                      "type": "integer",
++                      "default": 5,
++                      "minimum": 1,
++                      "maximum": 254
++                    },
++                    "http_statuses": {
++                      "type": "array",
++                      "uniqueItems": true,
++                      "default": [429, 404, 500, 501, 502, 503, 504, 505],
++                      "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                      "minItems": 1
++                    },
++                    "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                    "timeouts": { "type": "integer", "default": 3, "minimum": 1, "maximum": 254 },
++                    "tcp_failures": {
++                      "type": "integer",
++                      "default": 2,
++                      "minimum": 1,
++                      "maximum": 254
++                    }
++                  }
++                },
++                "https_verify_certificate": { "type": "boolean", "default": true }
++              }
++            },
++            "passive": {
++              "type": "object",
++              "properties": {
++                "type": { "type": "string", "enum": ["http", "https", "tcp"], "default": "http" },
++                "unhealthy": {
++                  "type": "object",
++                  "properties": {
++                    "http_statuses": {
++                      "type": "array",
++                      "uniqueItems": true,
++                      "default": [429, 500, 503],
++                      "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                      "minItems": 1
++                    },
++                    "timeouts": { "type": "integer", "default": 7, "minimum": 1, "maximum": 254 },
++                    "http_failures": {
++                      "type": "integer",
++                      "default": 5,
++                      "minimum": 1,
++                      "maximum": 254
++                    },
++                    "tcp_failures": {
++                      "type": "integer",
++                      "default": 2,
++                      "minimum": 1,
++                      "maximum": 254
++                    }
++                  }
++                },
++                "healthy": {
++                  "type": "object",
++                  "properties": {
++                    "http_statuses": {
++                      "type": "array",
++                      "uniqueItems": true,
++                      "default": [
++                        200,
++                        201,
++                        202,
++                        203,
++                        204,
++                        205,
++                        206,
++                        207,
++                        208,
++                        226,
++                        300,
++                        301,
++                        302,
++                        303,
++                        304,
++                        305,
++                        306,
++                        307,
++                        308
++                      ],
++                      "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                      "minItems": 1
++                    },
++                    "successes": { "type": "integer", "default": 5, "minimum": 1, "maximum": 254 }
++                  }
++                }
++              }
++            }
++          },
++          "additionalProperties": false
++        },
++        "nodes": {
++          "anyOf": [
++            {
++              "type": "object",
++              "patternProperties": {
++                ".*": { "type": "integer", "minimum": 0, "description": "weight of node" }
++              },
++              "minProperties": 1
++            },
++            {
++              "type": "array",
++              "items": {
++                "type": "object",
++                "properties": {
++                  "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                  "port": { "type": "integer", "minimum": 1, "description": "port of node" },
++                  "weight": { "type": "integer", "minimum": 0, "description": "weight of node" },
++                  "metadata": { "type": "object", "description": "metadata of node" }
++                },
++                "required": ["host", "port", "weight"]
++              },
++              "minItems": 1
++            }
++          ]
++        }
++      },
++      "anyOf": [
++        { "required": ["type", "nodes"] },
++        { "required": ["type", "k8s_deployment_info"] },
++        { "required": ["type", "service_name"] }
++      ]
++    },
++    "route": {
++      "type": "object",
++      "additionalProperties": false,
++      "not": { "anyOf": [{ "required": ["script", "plugins"] }] },
++      "properties": {
++        "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++        "methods": {
++          "type": "array",
++          "items": {
++            "type": "string",
++            "enum": [
++              "GET",
++              "POST",
++              "PUT",
++              "DELETE",
++              "PATCH",
++              "HEAD",
++              "OPTIONS",
++              "CONNECT",
++              "TRACE"
++            ],
++            "description": "HTTP method"
++          },
++          "uniqueItems": true
++        },
++        "create_time": { "type": "integer" },
++        "hosts": {
++          "type": "array",
++          "items": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++          "uniqueItems": true
++        },
++        "name": { "type": "string", "maxLength": 50 },
++        "filter_func": { "type": "string", "minLength": 10, "pattern": "^function" },
++        "uri": { "type": "string", "minLength": 1, "maxLength": 4096 },
++        "priority": { "type": "integer", "default": 0 },
++        "remote_addrs": {
++          "type": "array",
++          "items": {
++            "type": "string",
++            "anyOf": [
++              {
++                "title": "IPv4",
++                "type": "string",
++                "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++              },
++              {
++                "title": "IPv4/CIDR",
++                "type": "string",
++                "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++              },
++              {
++                "title": "IPv6",
++                "type": "string",
++                "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++              },
++              {
++                "title": "IPv6/CIDR",
++                "type": "string",
++                "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++              }
++            ],
++            "description": "client IP"
++          },
++          "uniqueItems": true
++        },
++        "upstream": {
++          "type": "object",
++          "additionalProperties": false,
++          "properties": {
++            "create_time": { "type": "integer" },
++            "hash_on": {
++              "type": "string",
++              "enum": ["vars", "header", "cookie", "consumer"],
++              "default": "vars"
++            },
++            "pass_host": {
++              "type": "string",
++              "default": "pass",
++              "enum": ["pass", "node", "rewrite"],
++              "description": "mod of host passing"
++            },
++            "type": {
++              "type": "string",
++              "enum": ["chash", "roundrobin", "ewma"],
++              "description": "algorithms of load balancing"
++            },
++            "enable_websocket": {
++              "type": "boolean",
++              "description": "enable websocket for request"
++            },
++            "update_time": { "type": "integer" },
++            "labels": {
++              "type": "object",
++              "maxProperties": 16,
++              "patternProperties": {
++                ".*": {
++                  "type": "string",
++                  "maxLength": 64,
++                  "minLength": 1,
++                  "pattern": "^[a-zA-Z0-9-_.]+$",
++                  "description": "value of label"
++                }
++              },
++              "description": "key/value pairs to specify attributes"
++            },
++            "retries": { "type": "integer", "minimum": 0 },
++            "service_name": { "type": "string", "maxLength": 50 },
++            "id": {
++              "anyOf": [
++                {
++                  "type": "string",
++                  "minLength": 1,
++                  "maxLength": 64,
++                  "pattern": "^[a-zA-Z0-9-_]+$"
++                },
++                { "type": "integer", "minimum": 1 }
++              ]
++            },
++            "key": {
++              "type": "string",
++              "description": "the key of chash for dynamic load balancing"
++            },
++            "name": { "type": "string", "maxLength": 50 },
++            "upstream_host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++            "timeout": {
++              "type": "object",
++              "properties": {
++                "send": { "type": "number", "minimum": 0 },
++                "read": { "type": "number", "minimum": 0 },
++                "connect": { "type": "number", "minimum": 0 }
++              },
++              "required": ["connect", "send", "read"]
++            },
++            "k8s_deployment_info": {
++              "type": "object",
++              "properties": {
++                "port": { "type": "number", "minimum": 0 },
++                "deploy_name": { "type": "string", "description": "k8s deployment name" },
++                "service_name": { "type": "string", "description": "k8s service name" },
++                "namespace": { "type": "string", "description": "k8s namespace" },
++                "backend_type": {
++                  "type": "string",
++                  "description": "k8s service name",
++                  "enum": ["svc", "pod"],
++                  "default": "pod"
++                }
++              },
++              "anyOf": [
++                { "required": ["namespace", "deploy_name", "port"] },
++                { "required": ["namespace", "service_name", "port"] }
++              ]
++            },
++            "desc": { "type": "string", "maxLength": 256 },
++            "checks": {
++              "type": "object",
++              "anyOf": [{ "required": ["active"] }, { "required": ["active", "passive"] }],
++              "properties": {
++                "active": {
++                  "type": "object",
++                  "properties": {
++                    "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                    "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
++                    "http_path": { "type": "string", "default": "/" },
++                    "req_headers": {
++                      "type": "array",
++                      "items": { "type": "string", "uniqueItems": true },
++                      "minItems": 1
++                    },
++                    "type": {
++                      "type": "string",
++                      "enum": ["http", "https", "tcp"],
++                      "default": "http"
++                    },
++                    "timeout": { "type": "number", "default": 1 },
++                    "concurrency": { "type": "integer", "default": 10 },
++                    "healthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [200, 302],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                        "successes": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "unhealthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_failures": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [429, 404, 500, 501, 502, 503, 504, 505],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "interval": { "type": "integer", "minimum": 1, "default": 0 },
++                        "timeouts": {
++                          "type": "integer",
++                          "default": 3,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "tcp_failures": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "https_verify_certificate": { "type": "boolean", "default": true }
++                  }
++                },
++                "passive": {
++                  "type": "object",
++                  "properties": {
++                    "type": {
++                      "type": "string",
++                      "enum": ["http", "https", "tcp"],
++                      "default": "http"
++                    },
++                    "unhealthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [429, 500, 503],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "timeouts": {
++                          "type": "integer",
++                          "default": 7,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "http_failures": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        },
++                        "tcp_failures": {
++                          "type": "integer",
++                          "default": 2,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    },
++                    "healthy": {
++                      "type": "object",
++                      "properties": {
++                        "http_statuses": {
++                          "type": "array",
++                          "uniqueItems": true,
++                          "default": [
++                            200,
++                            201,
++                            202,
++                            203,
++                            204,
++                            205,
++                            206,
++                            207,
++                            208,
++                            226,
++                            300,
++                            301,
++                            302,
++                            303,
++                            304,
++                            305,
++                            306,
++                            307,
++                            308
++                          ],
++                          "items": { "type": "integer", "minimum": 200, "maximum": 599 },
++                          "minItems": 1
++                        },
++                        "successes": {
++                          "type": "integer",
++                          "default": 5,
++                          "minimum": 1,
++                          "maximum": 254
++                        }
++                      }
++                    }
++                  }
++                }
++              },
++              "additionalProperties": false
++            },
++            "nodes": {
++              "anyOf": [
++                {
++                  "type": "object",
++                  "patternProperties": {
++                    ".*": { "type": "integer", "minimum": 0, "description": "weight of node" }
++                  },
++                  "minProperties": 1
++                },
++                {
++                  "type": "array",
++                  "items": {
++                    "type": "object",
++                    "properties": {
++                      "host": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++                      "port": { "type": "integer", "minimum": 1, "description": "port of node" },
++                      "weight": {
++                        "type": "integer",
++                        "minimum": 0,
++                        "description": "weight of node"
++                      },
++                      "metadata": { "type": "object", "description": "metadata of node" }
++                    },
++                    "required": ["host", "port", "weight"]
++                  },
++                  "minItems": 1
++                }
++              ]
++            }
++          },
++          "anyOf": [
++            { "required": ["type", "nodes"] },
++            { "required": ["type", "k8s_deployment_info"] },
++            { "required": ["type", "service_name"] }
++          ]
++        },
++        "remote_addr": {
++          "type": "string",
++          "anyOf": [
++            {
++              "title": "IPv4",
++              "type": "string",
++              "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++            },
++            {
++              "title": "IPv4/CIDR",
++              "type": "string",
++              "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++            },
++            {
++              "title": "IPv6",
++              "type": "string",
++              "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++            },
++            {
++              "title": "IPv6/CIDR",
++              "type": "string",
++              "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++            }
++          ],
++          "description": "client IP"
++        },
++        "service_protocol": { "enum": ["grpc", "http"] },
++        "upstream_id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "update_time": { "type": "integer" },
++        "id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "script": { "type": "string", "minLength": 10, "maxLength": 102400 },
++        "service_id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        },
++        "labels": {
++          "type": "object",
++          "maxProperties": 16,
++          "patternProperties": {
++            ".*": {
++              "type": "string",
++              "maxLength": 64,
++              "minLength": 1,
++              "pattern": "^[a-zA-Z0-9-_.]+$",
++              "description": "value of label"
++            }
++          },
++          "description": "key/value pairs to specify attributes"
++        },
++        "plugins": { "type": "object" },
++        "uris": {
++          "type": "array",
++          "items": { "type": "string", "description": "HTTP uri" },
++          "uniqueItems": true
++        },
++        "vars": {
++          "type": "array",
++          "items": {
++            "type": "array",
++            "items": {
++              "maxItems": 3,
++              "anyOf": [{ "type": "string" }, { "type": "number" }],
++              "minItems": 2
++            },
++            "description": "Nginx builtin variable name and value"
++          }
++        },
++        "desc": { "type": "string", "maxLength": 256 }
++      },
++      "anyOf": [
++        { "required": ["plugins", "uri"] },
++        { "required": ["upstream", "uri"] },
++        { "required": ["upstream_id", "uri"] },
++        { "required": ["service_id", "uri"] },
++        { "required": ["plugins", "uris"] },
++        { "required": ["upstream", "uris"] },
++        { "required": ["upstream_id", "uris"] },
++        { "required": ["service_id", "uris"] },
++        { "required": ["script", "uri"] },
++        { "required": ["script", "uris"] }
++      ]
++    }
++  },
++  "plugins": {
++    "limit-req": {
++      "type": "object",
++      "properties": {
++        "key": {
++          "type": "string",
++          "enum": [
++            "remote_addr",
++            "server_addr",
++            "http_x_real_ip",
++            "http_x_forwarded_for",
++            "consumer_name"
++          ]
++        },
++        "rate": { "type": "number", "minimum": 0 },
++        "burst": { "type": "number", "minimum": 0 },
++        "rejected_code": { "type": "integer", "minimum": 200, "default": 503 }
++      },
++      "required": ["rate", "burst", "key"]
++    },
++    "request-validation": {
++      "type": "object",
++      "properties": { "header_schema": { "type": "object" }, "body_schema": { "type": "object" } },
++      "anyOf": [{ "required": ["body_schema"] }, { "required": ["header_schema"] }]
++    },
++    "referer-restriction": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "bypass_missing": { "type": "boolean", "default": false },
++        "whitelist": {
++          "type": "array",
++          "items": { "type": "string", "pattern": "^\\*?[0-9a-zA-Z-.]+$" },
++          "minItems": 1
++        }
++      },
++      "required": ["whitelist"]
++    },
++    "zipkin": {
++      "type": "object",
++      "properties": {
++        "sample_ratio": { "type": "number", "minimum": 1e-5, "maximum": 1 },
++        "service_name": {
++          "type": "string",
++          "default": "APISIX",
++          "description": "service name for zipkin reporter"
++        },
++        "server_addr": {
++          "type": "string",
++          "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$",
++          "description": "default is $server_addr, you can speific your external ip address"
++        },
++        "endpoint": { "type": "string" }
++      },
++      "required": ["endpoint", "sample_ratio"]
++    },
++    "jwt-auth": {
++      "type": "object",
++      "properties": {
++        "key": { "type": "string" },
++        "exp": { "type": "integer", "minimum": 1 },
++        "base64_secret": { "type": "boolean", "default": false },
++        "algorithm": { "type": "string", "enum": ["HS256", "HS512", "RS256"], "default": "HS256" },
++        "secret": { "type": "string" }
++      }
++    },
++    "wolf-rbac": {
++      "type": "object",
++      "properties": {
++        "header_prefix": { "type": "string", "default": "X-" },
++        "appid": { "type": "string", "default": "unset" },
++        "server": { "type": "string", "default": "http://127.0.0.1:10080" }
++      }
++    },
++    "limit-conn": {
++      "type": "object",
++      "properties": {
++        "key": {
++          "type": "string",
++          "enum": ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for"]
++        },
++        "burst": { "type": "integer", "minimum": 0 },
++        "conn": { "type": "integer", "minimum": 0 },
++        "rejected_code": { "type": "integer", "minimum": 200, "default": 503 },
++        "default_conn_delay": { "type": "number", "minimum": 0 }
++      },
++      "required": ["conn", "burst", "default_conn_delay", "key"]
++    },
++    "prometheus": { "type": "object", "additionalProperties": false },
++    "example-plugin": {
++      "type": "object",
++      "properties": {
++        "port": { "type": "integer" },
++        "i": { "type": "number", "minimum": 0 },
++        "s": { "type": "string" },
++        "t": { "type": "array", "minItems": 1 },
++        "ip": { "type": "string" }
++      },
++      "required": ["i"]
++    },
++    "tcp-logger": {
++      "type": "object",
++      "properties": {
++        "host": { "type": "string" },
++        "port": { "type": "integer", "minimum": 0 },
++        "retry_delay": { "type": "integer", "minimum": 0, "default": 1 },
++        "include_req_body": { "type": "boolean", "default": false },
++        "batch_max_size": { "type": "integer", "minimum": 1, "default": 1000 },
++        "max_retry_count": { "type": "integer", "minimum": 0, "default": 0 },
++        "timeout": { "type": "integer", "minimum": 1, "default": 1000 },
++        "inactive_timeout": { "type": "integer", "minimum": 1, "default": 5 },
++        "buffer_duration": { "type": "integer", "minimum": 1, "default": 60 },
++        "name": { "type": "string", "default": "tcp logger" },
++        "tls": { "type": "boolean", "default": false },
++        "tls_options": { "type": "string" }
++      },
++      "required": ["host", "port"]
++    },
++    "request-id": {
++      "type": "object",
++      "properties": {
++        "include_in_response": { "type": "boolean", "default": true },
++        "header_name": { "type": "string", "default": "X-Request-Id" }
++      }
++    },
++    "proxy-rewrite": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "host": {
++          "type": "string",
++          "pattern": "^[0-9a-zA-Z-.]+$",
++          "description": "new host for upstream"
++        },
++        "regex_uri": {
++          "type": "array",
++          "maxItems": 2,
++          "items": { "type": "string", "description": "regex uri" },
++          "minItems": 2,
++          "description": "new uri that substitute from client uri for upstream, lower priority than uri property"
++        },
++        "headers": {
++          "type": "object",
++          "minProperties": 1,
++          "description": "new headers for request"
++        },
++        "uri": {
++          "type": "string",
++          "maxLength": 4096,
++          "minLength": 1,
++          "pattern": "^\\/.*",
++          "description": "new uri for upstream"
++        },
++        "scheme": {
++          "type": "string",
++          "enum": ["http", "https"],
++          "description": "new scheme for upstream"
++        }
++      },
++      "minProperties": 1
++    },
++    "basic-auth": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": [],
++      "title": "work with route or service object"
++    },
++    "echo": {
++      "type": "object",
++      "additionalProperties": false,
++      "anyOf": [
++        { "required": ["before_body"] },
++        { "required": ["body"] },
++        { "required": ["after_body"] }
++      ],
++      "properties": {
++        "body": { "type": "string", "description": "body to replace upstream response." },
++        "after_body": {
++          "type": "string",
++          "description": "body after the modification of filter phase."
++        },
++        "auth_value": { "type": "string", "description": "auth value" },
++        "before_body": { "type": "string", "description": "body before the filter phase." },
++        "headers": {
++          "type": "object",
++          "minProperties": 1,
++          "description": "new headers for response"
++        }
++      },
++      "minProperties": 1
++    },
++    "limit-count": {
++      "type": "object",
++      "dependencies": {
++        "policy": {
++          "oneOf": [
++            { "properties": { "policy": { "enum": ["local"] } } },
++            {
++              "properties": {
++                "redis_password": { "type": "string", "minLength": 0 },
++                "redis_host": { "type": "string", "minLength": 2 },
++                "redis_timeout": { "type": "integer", "minimum": 1, "default": 1000 },
++                "redis_port": { "type": "integer", "minimum": 1, "default": 6379 },
++                "policy": { "enum": ["redis"] }
++              },
++              "required": ["redis_host"]
++            }
++          ]
++        }
++      },
++      "properties": {
++        "key": {
++          "type": "string",
++          "enum": ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for"]
++        },
++        "time_window": { "type": "integer", "minimum": 0 },
++        "count": { "type": "integer", "minimum": 0 },
++        "rejected_code": { "type": "integer", "default": 503, "minimum": 200, "maximum": 600 },
++        "policy": { "type": "string", "enum": ["local", "redis"], "default": "local" }
++      },
++      "required": ["count", "time_window", "key"]
++    },
++    "key-auth": { "type": "object", "properties": { "key": { "type": "string" } } },
++    "openid-connect": {
++      "type": "object",
++      "properties": {
++        "client_id": { "type": "string" },
++        "bearer_only": { "type": "boolean" },
++        "discovery": { "type": "string" },
++        "introspection_endpoint": { "type": "string" },
++        "token_signing_alg_values_expected": { "type": "string" },
++        "public_key": { "type": "string" },
++        "scope": { "type": "string" },
++        "logout_path": { "type": "string" },
++        "client_secret": { "type": "string" },
++        "redirect_uri": { "type": "string" },
++        "realm": { "type": "string" },
++        "introspection_endpoint_auth_method": { "type": "string" },
++        "timeout": { "type": "integer", "minimum": 1 },
++        "ssl_verify": { "type": "boolean" }
++      },
++      "required": ["client_id", "client_secret", "discovery"]
++    },
++    "log-rotate": { "type": "object", "properties": [], "additionalProperties": false },
++    "uri-blocker": {
++      "type": "object",
++      "properties": {
++        "block_rules": {
++          "type": "array",
++          "items": { "type": "string", "minLength": 1, "maxLength": 4096 },
++          "uniqueItems": true
++        },
++        "rejected_code": { "type": "integer", "minimum": 200, "default": 403 }
++      },
++      "required": ["block_rules"]
++    },
++    "hmac-auth": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": [],
++      "title": "work with route or service object"
++    },
++    "udp-logger": {
++      "type": "object",
++      "properties": {
++        "host": { "type": "string" },
++        "port": { "type": "integer", "minimum": 0 },
++        "timeout": { "type": "integer", "minimum": 1, "default": 3 },
++        "include_req_body": { "type": "boolean", "default": false },
++        "batch_max_size": { "type": "integer", "minimum": 1, "default": 1000 },
++        "inactive_timeout": { "type": "integer", "minimum": 1, "default": 5 },
++        "buffer_duration": { "type": "integer", "minimum": 1, "default": 60 },
++        "name": { "type": "string", "default": "udp logger" }
++      },
++      "required": ["host", "port"]
++    },
++    "response-rewrite": {
++      "type": "object",
++      "additionalProperties": false,
++      "properties": {
++        "headers": {
++          "type": "object",
++          "minProperties": 1,
++          "description": "new headers for repsonse"
++        },
++        "status_code": {
++          "type": "integer",
++          "maximum": 598,
++          "minimum": 200,
++          "description": "new status code for repsonse"
++        },
++        "body": { "type": "string", "description": "new body for repsonse" },
++        "body_base64": {
++          "type": "boolean",
++          "default": false,
++          "description": "whether new body for repsonse need base64 decode before return"
++        }
++      },
++      "minProperties": 1
++    },
++    "ip-restriction": {
++      "type": "object",
++      "oneOf": [
++        {
++          "title": "whitelist",
++          "additionalProperties": false,
++          "properties": {
++            "whitelist": {
++              "type": "array",
++              "items": {
++                "anyOf": [
++                  {
++                    "title": "IPv4",
++                    "type": "string",
++                    "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++                  },
++                  {
++                    "title": "IPv4/CIDR",
++                    "type": "string",
++                    "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++                  },
++                  {
++                    "title": "IPv6",
++                    "type": "string",
++                    "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++                  },
++                  {
++                    "title": "IPv6/CIDR",
++                    "type": "string",
++                    "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++                  }
++                ]
++              },
++              "minItems": 1
++            }
++          },
++          "required": ["whitelist"]
++        },
++        {
++          "title": "blacklist",
++          "additionalProperties": false,
++          "properties": {
++            "blacklist": {
++              "type": "array",
++              "items": {
++                "anyOf": [
++                  {
++                    "title": "IPv4",
++                    "type": "string",
++                    "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
++                  },
++                  {
++                    "title": "IPv4/CIDR",
++                    "type": "string",
++                    "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$"
++                  },
++                  {
++                    "title": "IPv6",
++                    "type": "string",
++                    "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$"
++                  },
++                  {
++                    "title": "IPv6/CIDR",
++                    "type": "string",
++                    "pattern": "^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$"
++                  }
++                ]
++              },
++              "minItems": 1
++            }
++          },
++          "required": ["blacklist"]
++        }
++      ]
++    },
++    "skywalking": {
++      "type": "object",
++      "required": ["endpoint"],
++      "properties": {
++        "sample_ratio": { "type": "number", "default": 1, "minimum": 1e-5, "maximum": 1 },
++        "endpoint": { "type": "string" }
++      },
++      "service_name": {
++        "type": "string",
++        "default": "APISIX",
++        "description": "service name for skywalking"
++      }
++    },
++    "syslog": {
++      "type": "object",
++      "properties": {
++        "host": { "type": "string" },
++        "port": { "type": "integer" },
++        "max_retry_times": { "type": "integer", "minimum": 1, "default": 1 },
++        "drop_limit": { "type": "integer", "default": 1048576 },
++        "include_req_body": { "type": "boolean", "default": false },
++        "buffer_duration": { "type": "integer", "minimum": 1, "default": 60 },
++        "batch_max_size": { "type": "integer", "minimum": 1, "default": 1000 },
++        "timeout": { "type": "integer", "minimum": 1, "default": 3 },
++        "name": { "type": "string", "default": "sys logger" },
++        "pool_size": { "type": "integer", "minimum": 5, "default": 5 },
++        "retry_interval": { "type": "integer", "minimum": 0, "default": 1 },
++        "sock_type": { "type": "string", "enum": ["tcp", "udp"], "default": "tcp" },
++        "tls": { "type": "boolean", "default": false },
++        "flush_limit": { "type": "integer", "minimum": 1, "default": 4096 }
++      },
++      "required": ["host", "port"]
++    },
++    "kafka-logger": {
++      "type": "object",
++      "properties": {
++        "kafka_topic": { "type": "string" },
++        "batch_max_size": { "type": "integer", "minimum": 1, "default": 1000 },
++        "retry_delay": { "type": "integer", "minimum": 0, "default": 1 },
++        "include_req_body": { "type": "boolean", "default": false },
++        "meta_format": { "type": "string", "enum": ["default", "origin"], "default": "default" },
++        "key": { "type": "string" },
++        "max_retry_count": { "type": "integer", "minimum": 0, "default": 0 },
++        "timeout": { "type": "integer", "minimum": 1, "default": 3 },
++        "inactive_timeout": { "type": "integer", "minimum": 1, "default": 5 },
++        "name": { "type": "string", "default": "kafka logger" },
++        "buffer_duration": { "type": "integer", "minimum": 1, "default": 60 },
++        "broker_list": { "type": "object" }
++      },
++      "required": ["broker_list", "kafka_topic", "key"]
++    },
++    "consumer-restriction": {
++      "type": "object",
++      "properties": {
++        "type": {
++          "type": "string",
++          "enum": ["consumer_name", "service_id"],
++          "default": "consumer_name"
++        },
++        "blacklist": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
++        "rejected_code": { "type": "integer", "minimum": 200, "default": 403 },
++        "whitelist": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
++      },
++      "oneOf": [{ "required": ["whitelist"] }, { "required": ["blacklist"] }]
++    },
++    "proxy-cache": {
++      "type": "object",
++      "properties": {
++        "cache_method": {
++          "type": "array",
++          "uniqueItems": true,
++          "default": ["GET", "HEAD"],
++          "items": {
++            "type": "string",
++            "enum": [
++              "GET",
++              "POST",
++              "PUT",
++              "DELETE",
++              "PATCH",
++              "HEAD",
++              "OPTIONS",
++              "CONNECT",
++              "TRACE"
++            ],
++            "description": "http method"
++          },
++          "minItems": 1
++        },
++        "cache_http_status": {
++          "type": "array",
++          "uniqueItems": true,
++          "default": [200, 301, 404],
++          "items": {
++            "type": "integer",
++            "maximum": 599,
++            "minimum": 200,
++            "description": "http response status"
++          },
++          "minItems": 1
++        },
++        "cache_key": {
++          "type": "array",
++          "default": ["$host", "$request_uri"],
++          "items": {
++            "type": "string",
++            "pattern": "(^[^\\$].+$|^\\$[0-9a-zA-Z_]+$)",
++            "description": "a key for caching"
++          },
++          "minItems": 1
++        },
++        "cache_zone": { "type": "string", "minLength": 1 },
++        "no_cache": {
++          "type": "array",
++          "items": { "type": "string", "pattern": "(^[^\\$].+$|^\\$[0-9a-zA-Z_]+$)" },
++          "minItems": 1
++        },
++        "cache_bypass": {
++          "type": "array",
++          "items": { "type": "string", "pattern": "(^[^\\$].+$|^\\$[0-9a-zA-Z_]+$)" },
++          "minItems": 1
++        },
++        "hide_cache_headers": { "type": "boolean", "default": false }
++      },
++      "required": ["cache_zone"]
++    },
++    "serverless-post-function": {
++      "type": "object",
++      "properties": {
++        "phase": {
++          "type": "string",
++          "enum": ["rewrite", "access", "header_filter", "body_filter", "log", "balancer"]
++        },
++        "functions": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
++      },
++      "required": ["functions"]
++    },
++    "fault-injection": {
++      "type": "object",
++      "properties": {
++        "delay": {
++          "type": "object",
++          "properties": { "duration": { "type": "number", "minimum": 0 } },
++          "minProperties": 1
++        },
++        "abort": {
++          "type": "object",
++          "properties": {
++            "body": { "type": "string", "minLength": 0 },
++            "http_status": { "type": "integer", "minimum": 200 }
++          },
++          "minProperties": 1
++        }
++      },
++      "minProperties": 1
++    },
++    "redirect": {
++      "type": "object",
++      "properties": {
++        "http_to_https": { "type": "boolean" },
++        "uri": { "type": "string", "minLength": 2 },
++        "ret_code": { "type": "integer", "minimum": 200, "default": 302 }
++      },
++      "oneOf": [{ "required": ["uri"] }, { "required": ["http_to_https"] }]
++    },
++    "http-logger": {
++      "type": "object",
++      "properties": {
++        "batch_max_size": { "type": "integer", "minimum": 1, "default": 1000 },
++        "retry_delay": { "type": "integer", "minimum": 0, "default": 1 },
++        "include_req_body": { "type": "boolean", "default": false },
++        "concat_method": { "type": "string", "enum": ["json", "new_line"], "default": "json" },
++        "max_retry_count": { "type": "integer", "minimum": 0, "default": 0 },
++        "timeout": { "type": "integer", "minimum": 1, "default": 3 },
++        "inactive_timeout": { "type": "integer", "minimum": 1, "default": 5 },
++        "buffer_duration": { "type": "integer", "minimum": 1, "default": 60 },
++        "name": { "type": "string", "default": "http logger" },
++        "uri": { "type": "string" },
++        "auth_header": { "type": "string", "default": "" }
++      },
++      "required": ["uri"]
++    },
++    "authz-keycloak": {
++      "type": "object",
++      "properties": {
++        "keepalive": { "type": "boolean", "default": true },
++        "permissions": {
++          "type": "array",
++          "items": { "type": "string", "minLength": 1, "maxLength": 100 },
++          "uniqueItems": true
++        },
++        "policy_enforcement_mode": {
++          "type": "string",
++          "enum": ["ENFORCING", "PERMISSIVE"],
++          "default": "ENFORCING"
++        },
++        "ssl_verify": { "type": "boolean", "default": true },
++        "token_endpoint": { "type": "string", "minLength": 1, "maxLength": 4096 },
++        "timeout": { "type": "integer", "minimum": 1000, "default": 3000 },
++        "audience": { "type": "string", "minLength": 1, "maxLength": 100 },
++        "keepalive_pool": { "type": "integer", "minimum": 1, "default": 5 },
++        "keepalive_timeout": { "type": "integer", "minimum": 1000, "default": 60000 },
++        "grant_type": {
++          "type": "string",
++          "maxLength": 100,
++          "minLength": 1,
++          "enum": ["urn:ietf:params:oauth:grant-type:uma-ticket"],
++          "default": "urn:ietf:params:oauth:grant-type:uma-ticket"
++        }
++      },
++      "required": ["token_endpoint"]
++    },
++    "serverless-pre-function": {
++      "type": "object",
++      "properties": {
++        "phase": {
++          "type": "string",
++          "enum": ["rewrite", "access", "header_filter", "body_filter", "log", "balancer"]
++        },
++        "functions": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
++      },
++      "required": ["functions"]
++    },
++    "cors": {
++      "type": "object",
++      "properties": {
++        "allow_credential": {
++          "type": "boolean",
++          "default": false,
++          "description": "allow client append crendential. according to CORS specification,if you set this option to 'true', you can not use '*' for other options."
++        },
++        "max_age": {
++          "type": "integer",
++          "default": 5,
++          "description": "maximum number of seconds the results can be cached.-1 mean no cached,the max value is depend on browser,more detail plz check MDN. default: 5."
++        },
++        "allow_origins": {
++          "type": "string",
++          "default": "*",
++          "description": "you can use '*' to allow all origins when no credentials,'**' to allow forcefully(it will bring some security risks, be carefully),multiple origin use ',' to split. default: *."
++        },
++        "allow_methods": {
++          "type": "string",
++          "default": "*",
++          "description": "you can use '*' to allow all methods when no credentials and '**','**' to allow forcefully(it will bring some security risks, be carefully),multiple method use ',' to split. default: *."
++        },
++        "expose_headers": {
++          "type": "string",
++          "default": "*",
++          "description": "you can use '*' to expose all header when no credentials,multiple header use ',' to split. default: *."
++        },
++        "allow_headers": {
++          "type": "string",
++          "default": "*",
++          "description": "you can use '*' to allow all header when no credentials,'**' to allow forcefully(it will bring some security risks, be carefully),multiple header use ',' to split. default: *."
++        }
++      }
++    },
++    "batch-requests": { "type": "object", "additionalProperties": false },
++    "grpc-transcode": {
++      "type": "object",
++      "required": ["proto_id", "service", "method"],
++      "properties": {
++        "pb_option": {
++          "type": "array",
++          "items": {
++            "type": "string",
++            "anyOf": [
++              {
++                "type": "string",
++                "enum": ["int64_as_number", "int64_as_string", "int64_as_hexstring"],
++                "description": "enum as result"
++              },
++              {
++                "type": "string",
++                "enum": ["ienum_as_name", "enum_as_value"],
++                "description": "int64 as result"
++              },
++              {
++                "type": "string",
++                "enum": [
++                  "auto_default_values",
++                  "no_default_values",
++                  "use_default_values",
++                  "use_default_metatable"
++                ],
++                "description": "default values option"
++              },
++              {
++                "type": "string",
++                "enum": ["enable_hooks", "disable_hooks"],
++                "description": "hooks option"
++              }
++            ]
++          },
++          "minItems": 1
++        },
++        "service": { "type": "string", "description": "the grpc service name" },
++        "method": { "type": "string", "description": "the method name in the grpc service." },
++        "deadline": {
++          "type": "number",
++          "default": 0,
++          "description": "deadline for grpc, millisecond"
++        },
++        "proto_id": {
++          "anyOf": [
++            { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-zA-Z0-9-_]+$" },
++            { "type": "integer", "minimum": 1 }
++          ]
++        }
++      },
++      "additionalProperties": true
++    },
++    "proxy-mirror": {
++      "type": "object",
++      "required": ["host"],
++      "properties": {
++        "host": {
++          "type": "string",
++          "pattern": "^http(s)?:\\/\\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:[0-9]{1,5})?$"
++        }
++      },
++      "minProperties": 1
++    },
++    "node-status": { "type": "object", "additionalProperties": false }
++  }
++}
diff --cc api/internal/core/store/test_case.json
index 0000000,77f524b..950edf3
mode 000000,100644..100644
--- a/api/internal/core/store/test_case.json
+++ b/api/internal/core/store/test_case.json
@@@ -1,0 -1,19 +1,19 @@@
+ {
+   "$schema": "http://json-schema.org/draft-04/schema#",
+   "type": "object",
+   "properties": {
 -    "name":  {
++    "name": {
+       "type": "string",
+       "minLength": 10
+     },
+     "email": {
+       "type": "string",
+       "maxLength": 10
+     },
+     "age": {
+       "type": "integer",
+       "minimum": 0
+     }
+   },
+   "additionalProperties": false
+ }