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

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


The following commit(s) were added to refs/heads/refactor by this push:
     new 9b5c198  fix: add test cases for refactored apis and fix bugs (#528)
9b5c198 is described below

commit 9b5c19854e3765b7bb5acd34bdd3f6f2f97f301c
Author: nic-chen <[email protected]>
AuthorDate: Fri Oct 2 11:16:29 2020 +0800

    fix: add test cases for refactored apis and fix bugs (#528)
    
    * test: delete mysql version test cases.
    
    * fix: add ssl test cases and bug fix
    
    * fix: list api should return an empty array not a null for client
    
    * test: consumer test cases
    
    * fix: code style
    
    * test: init etcd in github action
    
    * fix: skip checking generated file's license
    
    * feat: add store hub and flake id (#534)
    
    * feat: add store hub and flake id
    
    * feat: add store interface to easy est
    
    * fix CI failed
    
    Co-authored-by: Vinci Xu <[email protected]>
---
 .actions/ASF-Release.cfg                  |   5 +
 .github/workflows/api_ci.yml              |  32 +--
 api/internal/core/entity/entity.go        |  20 +-
 api/internal/core/store/store.go          |   5 +
 api/internal/core/store/store_test.go     |  13 +-
 api/internal/core/store/storehub.go       |  16 ++
 api/internal/handler/consumer/consumer.go |  18 +-
 api/internal/handler/service/service.go   |   6 +-
 api/internal/handler/ssl/ssl.go           |  77 ++++---
 api/internal/handler/upstream/upstream.go |   6 +-
 api/internal/utils/utils.go               |  16 ++
 api/internal/utils/utils_test.go          |  16 ++
 api/route/authentication_test.go          |   4 +-
 api/route/base.go                         |   4 +-
 api/route/base_test.go                    |  92 +++++++-
 api/route/consumer_test.go                |  46 ++--
 api/route/route_group_test.go             | 131 -----------
 api/route/route_test.go                   | 200 -----------------
 api/route/ssl_test.go                     |  36 +--
 api/route/zclear_test.go                  |  37 ----
 api/service/base_test.go                  |  25 ---
 api/service/consumer_test.go              | 133 -----------
 api/service/route_group_test.go           | 120 ----------
 api/service/route_test.go                 | 329 ----------------------------
 api/service/ssl_test.go                   | 352 ------------------------------
 api/service/upstream_test.go              | 108 ---------
 26 files changed, 275 insertions(+), 1572 deletions(-)

diff --git a/.actions/ASF-Release.cfg b/.actions/ASF-Release.cfg
index 6b4cd0b..7c31253 100644
--- a/.actions/ASF-Release.cfg
+++ b/.actions/ASF-Release.cfg
@@ -87,6 +87,11 @@ DISCLAIMER.txt
 LICENSE*.txt
 NOTICE.txt
 
+# Skip generated file
+api/internal/core/store/validate_mock.go
+api/internal/core/storage/storage_mock.go
+
+
 conf
 .actions/openwhisk-utilities
 
diff --git a/.github/workflows/api_ci.yml b/.github/workflows/api_ci.yml
index 0cec7ee..32206f7 100644
--- a/.github/workflows/api_ci.yml
+++ b/.github/workflows/api_ci.yml
@@ -4,9 +4,11 @@ on:
   push:
     branches:
       - master
+      - refactor
   pull_request:
     branches:
       - master
+      - refactor
 
 jobs:
 
@@ -16,44 +18,17 @@ jobs:
 
     services:
       etcd:
-        image: bitnami/etcd:3.3.13-r80
+        image: bitnami/etcd:3.4.13
         ports:
           - 2379:2379
           - 2380:2380
         env:
           ALLOW_NONE_AUTHENTICATION: yes
 
-      mysql:
-        image: mysql:8.0
-        env:
-          MYSQL_ROOT_PASSWORD: 123456
-        ports:
-            - '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
-
-    - 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: run Makefile
       run: |
         make license-check
@@ -77,4 +52,5 @@ jobs:
     - name: run test
       working-directory: ./api
       run: |
+        export APIX_ETCD_ENDPOINTS=127.0.0.1:2379
         go test ./...
diff --git a/api/internal/core/entity/entity.go 
b/api/internal/core/entity/entity.go
index 5dca9c8..0a38c82 100644
--- a/api/internal/core/entity/entity.go
+++ b/api/internal/core/entity/entity.go
@@ -140,15 +140,17 @@ type Consumer struct {
 }
 
 type SSL struct {
-       ID      string   `json:"id"`
-       Cert    string   `json:"cert"`
-       Key     string   `json:"key"`
-       Sni     string   `json:"sni"`
-       Snis    []string `json:"snis"`
-       Certs   []string `json:"certs"`
-       Keys    []string `json:"keys"`
-       ExpTime int      `json:"exptime"`
-       Status  int      `json:"status"`
+       ID            string   `json:"id"`
+       Cert          string   `json:"cert"`
+       Key           string   `json:"key"`
+       Sni           string   `json:"sni"`
+       Snis          []string `json:"snis"`
+       Certs         []string `json:"certs"`
+       Keys          []string `json:"keys"`
+       ExpTime       int64    `json:"exptime"`
+       Status        int      `json:"status"`
+       ValidityStart int64    `json:"validity_start"`
+       ValidityEnd   int64    `json:"validity_end"`
 }
 
 type Service struct {
diff --git a/api/internal/core/store/store.go b/api/internal/core/store/store.go
index 3d2d4b9..75c74a0 100644
--- a/api/internal/core/store/store.go
+++ b/api/internal/core/store/store.go
@@ -151,6 +151,11 @@ func (s *GenericStore) List(input ListInput) (*ListOutput, 
error) {
                ret = append(ret, s.cache[k])
        }
 
+       //should return an empty array not a null for client
+       if ret == nil {
+               ret = []interface{}{}
+       }
+
        output := &ListOutput{
                Rows:      ret,
                TotalSize: len(ret),
diff --git a/api/internal/core/store/store_test.go 
b/api/internal/core/store/store_test.go
index 38ab343..4f29abc 100644
--- a/api/internal/core/store/store_test.go
+++ b/api/internal/core/store/store_test.go
@@ -20,14 +20,17 @@ import (
        "context"
        "encoding/json"
        "fmt"
-       "github.com/apisix/manager-api/internal/core/entity"
-       "github.com/apisix/manager-api/internal/core/storage"
-       "github.com/stretchr/testify/assert"
-       "github.com/stretchr/testify/mock"
        "reflect"
        "strings"
        "testing"
        "time"
+
+       "github.com/shiningrush/droplet/data"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+
+       "github.com/apisix/manager-api/internal/core/entity"
+       "github.com/apisix/manager-api/internal/core/storage"
 )
 
 func TestNewGenericStore(t *testing.T) {
@@ -259,7 +262,7 @@ func TestGenericStore_Get(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: fmt.Errorf("id:not not found"),
+                       wantErr: data.ErrNotFound,
                },
        }
 
diff --git a/api/internal/core/store/storehub.go 
b/api/internal/core/store/storehub.go
index 5b26bd3..203c5bc 100644
--- a/api/internal/core/store/storehub.go
+++ b/api/internal/core/store/storehub.go
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package store
 
 import (
diff --git a/api/internal/handler/consumer/consumer.go 
b/api/internal/handler/consumer/consumer.go
index ed55d39..71d4b03 100644
--- a/api/internal/handler/consumer/consumer.go
+++ b/api/internal/handler/consumer/consumer.go
@@ -42,26 +42,26 @@ func NewHandler() (handler.RouteRegister, error) {
 }
 
 func (h *Handler) ApplyRoute(r *gin.Engine) {
-       r.GET("/apisix/admin/consumers/:id", wgin.Wraps(h.Get,
+       r.GET("/apisix/admin/consumers/:username", wgin.Wraps(h.Get,
                wrapper.InputType(reflect.TypeOf(GetInput{}))))
        r.GET("/apisix/admin/consumers", wgin.Wraps(h.List,
                wrapper.InputType(reflect.TypeOf(ListInput{}))))
        r.POST("/apisix/admin/consumers", wgin.Wraps(h.Create,
                wrapper.InputType(reflect.TypeOf(entity.Consumer{}))))
-       r.PUT("/apisix/admin/consumers/:id", wgin.Wraps(h.Update,
+       r.PUT("/apisix/admin/consumers/:username", wgin.Wraps(h.Update,
                wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
-       r.DELETE("/apisix/admin/consumers", wgin.Wraps(h.BatchDelete,
+       r.DELETE("/apisix/admin/consumers/:usernames", wgin.Wraps(h.BatchDelete,
                wrapper.InputType(reflect.TypeOf(BatchDelete{}))))
 }
 
 type GetInput struct {
-       ID string `auto_read:"id,path" validate:"required"`
+       Username string `auto_read:"username,path" validate:"required"`
 }
 
 func (h *Handler) Get(c droplet.Context) (interface{}, error) {
        input := c.Input().(*GetInput)
 
-       r, err := h.consumerStore.Get(input.ID)
+       r, err := h.consumerStore.Get(input.Username)
        if err != nil {
                return nil, err
        }
@@ -96,6 +96,7 @@ func (h *Handler) List(c droplet.Context) (interface{}, 
error) {
 func (h *Handler) Create(c droplet.Context) (interface{}, error) {
        input := c.Input().(*entity.Consumer)
 
+       //TODO: check duplicate username
        if err := h.consumerStore.Create(c.Context(), input); err != nil {
                return nil, err
        }
@@ -104,14 +105,15 @@ func (h *Handler) Create(c droplet.Context) (interface{}, 
error) {
 }
 
 type UpdateInput struct {
-       ID string `auto_read:"id,path"`
+       Username string `auto_read:"username,path"`
        entity.Consumer
 }
 
 func (h *Handler) Update(c droplet.Context) (interface{}, error) {
        input := c.Input().(*UpdateInput)
-       input.Consumer.ID = input.ID
+       input.Consumer.Username = input.Username
 
+       //TODO: if not exists, create
        if err := h.consumerStore.Update(c.Context(), &input.Consumer); err != 
nil {
                return nil, err
        }
@@ -120,7 +122,7 @@ func (h *Handler) Update(c droplet.Context) (interface{}, 
error) {
 }
 
 type BatchDelete struct {
-       UserNames string `auto_read:"usernames,query"`
+       UserNames string `auto_read:"usernames,path"`
 }
 
 func (h *Handler) BatchDelete(c droplet.Context) (interface{}, error) {
diff --git a/api/internal/handler/service/service.go 
b/api/internal/handler/service/service.go
index ee8b5c5..ac4619a 100644
--- a/api/internal/handler/service/service.go
+++ b/api/internal/handler/service/service.go
@@ -51,6 +51,8 @@ func (h *Handler) ApplyRoute(r *gin.Engine) {
                wrapper.InputType(reflect.TypeOf(entity.Service{}))))
        r.PUT("/apisix/admin/services/:id", wgin.Wraps(h.Update,
                wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
+       r.PATCH("/apisix/admin/services/:id", wgin.Wraps(h.Patch,
+               wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
        r.DELETE("/apisix/admin/services", wgin.Wraps(h.BatchDelete,
                wrapper.InputType(reflect.TypeOf(BatchDelete{}))))
 }
@@ -155,13 +157,13 @@ func (h *Handler) Patch(c droplet.Context) (interface{}, 
error) {
        } else {
                patch, err = jsonpatch.MakePatch(stored, input.Service)
                if err != nil {
-                       panic(err)
+                       return nil, err
                }
        }
 
        err = patch.Apply(&stored)
        if err != nil {
-               panic(err)
+               return nil, err
        }
 
        if err := h.serviceStore.Update(c.Context(), &stored); err != nil {
diff --git a/api/internal/handler/ssl/ssl.go b/api/internal/handler/ssl/ssl.go
index 52162fb..b7bd4bb 100644
--- a/api/internal/handler/ssl/ssl.go
+++ b/api/internal/handler/ssl/ssl.go
@@ -54,7 +54,7 @@ func (h *Handler) ApplyRoute(r *gin.Engine) {
                wrapper.InputType(reflect.TypeOf(ListInput{}))))
        r.POST("/apisix/admin/ssl", wgin.Wraps(h.Create,
                wrapper.InputType(reflect.TypeOf(entity.SSL{}))))
-       r.POST("/apisix/admin/ssl/validate", wgin.Wraps(h.Validate,
+       r.POST("/apisix/admin/check_ssl_cert", wgin.Wraps(h.Validate,
                wrapper.InputType(reflect.TypeOf(entity.SSL{}))))
        r.PUT("/apisix/admin/ssl/:id", wgin.Wraps(h.Update,
                wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
@@ -106,7 +106,14 @@ func (h *Handler) List(c droplet.Context) (interface{}, 
error) {
 func (h *Handler) Create(c droplet.Context) (interface{}, error) {
        input := c.Input().(*entity.SSL)
 
-       if err := h.sslStore.Create(c.Context(), input); err != nil {
+       ssl, err := ParseCert(input.Cert, input.Key)
+       if err != nil {
+               return nil, err
+       }
+
+       ssl.ID = input.ID
+
+       if err := h.sslStore.Create(c.Context(), ssl); err != nil {
                return nil, err
        }
 
@@ -202,42 +209,48 @@ func ParseCert(crt, key string) (*entity.SSL, error) {
 
        if err != nil {
                return nil, errors.New("Certificate resolution failed")
+       }
+
+       ssl := entity.SSL{}
+       //domain
+       snis := []string{}
+       if x509Cert.DNSNames != nil && len(x509Cert.DNSNames) > 0 {
+               snis = x509Cert.DNSNames
+       } else if x509Cert.IPAddresses != nil && len(x509Cert.IPAddresses) > 0 {
+               for _, ip := range x509Cert.IPAddresses {
+                       snis = append(snis, ip.String())
+               }
        } else {
-               ssl := entity.SSL{}
-               //domain
-               snis := []string{}
-               if x509Cert.DNSNames != nil && len(x509Cert.DNSNames) > 0 {
-                       snis = x509Cert.DNSNames
-               } else if x509Cert.IPAddresses != nil && 
len(x509Cert.IPAddresses) > 0 {
-                       for _, ip := range x509Cert.IPAddresses {
-                               snis = append(snis, ip.String())
+               if x509Cert.Subject.Names != nil && len(x509Cert.Subject.Names) 
> 1 {
+                       var attributeTypeNames = map[string]string{
+                               "2.5.4.6":  "C",
+                               "2.5.4.10": "O",
+                               "2.5.4.11": "OU",
+                               "2.5.4.3":  "CN",
+                               "2.5.4.5":  "SERIALNUMBER",
+                               "2.5.4.7":  "L",
+                               "2.5.4.8":  "ST",
+                               "2.5.4.9":  "STREET",
+                               "2.5.4.17": "POSTALCODE",
                        }
-               } else {
-                       if x509Cert.Subject.Names != nil && 
len(x509Cert.Subject.Names) > 1 {
-                               var attributeTypeNames = map[string]string{
-                                       "2.5.4.6":  "C",
-                                       "2.5.4.10": "O",
-                                       "2.5.4.11": "OU",
-                                       "2.5.4.3":  "CN",
-                                       "2.5.4.5":  "SERIALNUMBER",
-                                       "2.5.4.7":  "L",
-                                       "2.5.4.8":  "ST",
-                                       "2.5.4.9":  "STREET",
-                                       "2.5.4.17": "POSTALCODE",
-                               }
-                               for _, tv := range x509Cert.Subject.Names {
-                                       oidString := tv.Type.String()
-                                       typeName, ok := 
attributeTypeNames[oidString]
-                                       if ok && typeName == "CN" {
-                                               valueString := 
fmt.Sprint(tv.Value)
-                                               snis = append(snis, valueString)
-                                       }
+                       for _, tv := range x509Cert.Subject.Names {
+                               oidString := tv.Type.String()
+                               typeName, ok := attributeTypeNames[oidString]
+                               if ok && typeName == "CN" {
+                                       valueString := fmt.Sprint(tv.Value)
+                                       snis = append(snis, valueString)
                                }
                        }
                }
-
-               return &ssl, nil
        }
+
+       ssl.Snis = snis
+       ssl.Key = key
+       ssl.ValidityStart = x509Cert.NotBefore.Unix()
+       ssl.ValidityEnd = x509Cert.NotAfter.Unix()
+       ssl.Cert = crt
+
+       return &ssl, nil
 }
 
 func (h *Handler) Validate(c droplet.Context) (interface{}, error) {
diff --git a/api/internal/handler/upstream/upstream.go 
b/api/internal/handler/upstream/upstream.go
index 87a8dd0..9efb944 100644
--- a/api/internal/handler/upstream/upstream.go
+++ b/api/internal/handler/upstream/upstream.go
@@ -51,6 +51,8 @@ func (h *Handler) ApplyRoute(r *gin.Engine) {
                wrapper.InputType(reflect.TypeOf(entity.Upstream{}))))
        r.PUT("/apisix/admin/upstreams/:id", wgin.Wraps(h.Update,
                wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
+       r.PATCH("/apisix/admin/upstreams/:id", wgin.Wraps(h.Patch,
+               wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
        r.DELETE("/apisix/admin/upstreams", wgin.Wraps(h.BatchDelete,
                wrapper.InputType(reflect.TypeOf(BatchDelete{}))))
 }
@@ -158,13 +160,13 @@ func (h *Handler) Patch(c droplet.Context) (interface{}, 
error) {
        } else {
                patch, err = jsonpatch.MakePatch(stored, input.Upstream)
                if err != nil {
-                       panic(err)
+                       return nil, err
                }
        }
 
        err = patch.Apply(&stored)
        if err != nil {
-               panic(err)
+               return nil, err
        }
 
        if err := h.upstreamStore.Update(c.Context(), &stored); err != nil {
diff --git a/api/internal/utils/utils.go b/api/internal/utils/utils.go
index f28c1bf..a314df7 100644
--- a/api/internal/utils/utils.go
+++ b/api/internal/utils/utils.go
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package utils
 
 import (
diff --git a/api/internal/utils/utils_test.go b/api/internal/utils/utils_test.go
index f88a6e4..7856c9c 100644
--- a/api/internal/utils/utils_test.go
+++ b/api/internal/utils/utils_test.go
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package utils
 
 import (
diff --git a/api/route/authentication_test.go b/api/route/authentication_test.go
index c778048..952a689 100644
--- a/api/route/authentication_test.go
+++ b/api/route/authentication_test.go
@@ -27,7 +27,7 @@ var token string
 
 func TestUserLogin(t *testing.T) {
        // password error
-       handler.
+       testHandler.
                Post("/apisix/admin/user/login").
                Header("Content-Type", "application/x-www-form-urlencoded").
                Body("username=admin&password=admin1").
@@ -36,7 +36,7 @@ func TestUserLogin(t *testing.T) {
                End()
 
        // login success
-       sessionResponse := handler.
+       sessionResponse := testHandler.
                Post("/apisix/admin/user/login").
                Header("Content-Type", "application/x-www-form-urlencoded").
                Body("username=admin&password=admin").
diff --git a/api/route/base.go b/api/route/base.go
index e40bcc6..979e750 100644
--- a/api/route/base.go
+++ b/api/route/base.go
@@ -17,8 +17,6 @@
 package route
 
 import (
-       "github.com/apisix/manager-api/internal/handler/service"
-       "github.com/apisix/manager-api/internal/handler/upstream"
        "github.com/gin-contrib/pprof"
        "github.com/gin-contrib/sessions"
        "github.com/gin-contrib/sessions/cookie"
@@ -29,7 +27,9 @@ import (
        "github.com/apisix/manager-api/internal/handler"
        "github.com/apisix/manager-api/internal/handler/consumer"
        "github.com/apisix/manager-api/internal/handler/route"
+       "github.com/apisix/manager-api/internal/handler/service"
        "github.com/apisix/manager-api/internal/handler/ssl"
+       "github.com/apisix/manager-api/internal/handler/upstream"
 )
 
 func SetUpRouter() *gin.Engine {
diff --git a/api/route/base_test.go b/api/route/base_test.go
index fb9f27d..fdfd6f9 100644
--- a/api/route/base_test.go
+++ b/api/route/base_test.go
@@ -17,23 +17,105 @@
 package route
 
 import (
+       "reflect"
+       "strings"
+
        "github.com/api7/apitest"
-       "github.com/apisix/manager-api/conf"
+       dlog "github.com/shiningrush/droplet/log"
+       "github.com/spf13/viper"
+
+       "github.com/apisix/manager-api/internal/core/entity"
+       "github.com/apisix/manager-api/internal/core/storage"
+       "github.com/apisix/manager-api/internal/core/store"
+       "github.com/apisix/manager-api/log"
 )
 
-var handler *apitest.APITest
+var testHandler *apitest.APITest
 
 var (
        uriPrefix = "/apisix/admin"
 )
 
 func init() {
-       //init mysql connect
-       conf.InitializeMysql()
+       //init etcd
+       viper.SetEnvPrefix("APIX")
+       viper.AutomaticEnv()
+       dlog.DefLogger = log.DefLogger{}
+
+       if err := 
storage.InitETCDClient(strings.Split(viper.GetString("etcd_endpoints"), ",")); 
err != nil {
+               panic(err)
+       }
+
+       if err := initStores(); err != nil {
+               panic(err)
+       }
 
        r := SetUpRouter()
 
-       handler = apitest.
+       testHandler = apitest.
                New().
                Handler(r)
 }
+
+func initStores() error {
+       err := store.InitStore(store.HubKeyConsumer, store.GenericStoreOption{
+               BasePath: "/apisix/consumers",
+               ObjType:  reflect.TypeOf(entity.Consumer{}),
+               KeyFunc: func(obj interface{}) string {
+                       r := obj.(*entity.Consumer)
+                       return r.Username
+               },
+       })
+       if err != nil {
+               return err
+       }
+
+       err = store.InitStore(store.HubKeyRoute, store.GenericStoreOption{
+               BasePath: "/apisix/routes",
+               ObjType:  reflect.TypeOf(entity.Route{}),
+               KeyFunc: func(obj interface{}) string {
+                       r := obj.(*entity.Route)
+                       return r.ID
+               },
+       })
+       if err != nil {
+               return err
+       }
+
+       err = store.InitStore(store.HubKeyService, store.GenericStoreOption{
+               BasePath: "/apisix/services",
+               ObjType:  reflect.TypeOf(entity.Service{}),
+               KeyFunc: func(obj interface{}) string {
+                       r := obj.(*entity.Service)
+                       return r.ID
+               },
+       })
+       if err != nil {
+               return err
+       }
+
+       err = store.InitStore(store.HubKeySsl, store.GenericStoreOption{
+               BasePath: "/apisix/ssl",
+               ObjType:  reflect.TypeOf(entity.SSL{}),
+               KeyFunc: func(obj interface{}) string {
+                       r := obj.(*entity.SSL)
+                       return r.ID
+               },
+       })
+       if err != nil {
+               return err
+       }
+
+       err = store.InitStore(store.HubKeyUpstream, store.GenericStoreOption{
+               BasePath: "/apisix/upstreams",
+               ObjType:  reflect.TypeOf(entity.Upstream{}),
+               KeyFunc: func(obj interface{}) string {
+                       r := obj.(*entity.Upstream)
+                       return r.ID
+               },
+       })
+       if err != nil {
+               return err
+       }
+       return nil
+}
diff --git a/api/route/consumer_test.go b/api/route/consumer_test.go
index 9228ece..3793804 100644
--- a/api/route/consumer_test.go
+++ b/api/route/consumer_test.go
@@ -19,17 +19,16 @@ package route
 import (
        "net/http"
        "testing"
-
-       "github.com/apisix/manager-api/service"
 )
 
 func TestConsumer(t *testing.T) {
        // create ok
-       handler.
+       username1 := "e2e_test_consumer1"
+       testHandler.
                Post(uriPrefix+"/consumers").
                Header("Authorization", token).
                JSON(`{
-                       "username": "e2e_test_consumer1",
+                       "username": "` + username1 + `",
                        "plugins": {
                                "limit-count": {
                                        "count": 2,
@@ -48,11 +47,9 @@ func TestConsumer(t *testing.T) {
                Status(http.StatusOK).
                End()
 
-       c1, _ := service.GetConsumerByUserName("e2e_test_consumer1")
-
        //update ok
-       handler.
-               Put(uriPrefix + "/consumers/" + c1.ID.String()).
+       testHandler.
+               Put(uriPrefix + "/consumers/" + username1).
                JSON(`{
                        "username": "e2e_test_consumer1",
                        "plugins": {
@@ -73,26 +70,19 @@ func TestConsumer(t *testing.T) {
                Status(http.StatusOK).
                End()
 
-       // duplicate username
-       handler.
-               Post(uriPrefix + "/consumers").
-               JSON(`{
-                       "username": "e2e_test_consumer1",
-                       "plugins": {
-                               "limit-count": {
-                                       "count": 2,
-                                       "time_window": 60,
-                                       "rejected_code": 503,
-                                       "key": "remote_addr"
-                               },
-                               "basic-auth": {
-                                       "username": "foo",
-                                       "password": "bar"
-                               }
-                       },
-                       "desc": "test description"
-               }`).
+       //list
+       testHandler.
+               Get(uriPrefix + "/consumers").
+               Headers(map[string]string{"Authorization": token}).
                Expect(t).
-               Status(http.StatusBadRequest).
+               Status(http.StatusOK).
+               End()
+
+       //delete
+       testHandler.
+               Delete(uriPrefix + "/consumers/" + username1).
+               Expect(t).
+               Status(http.StatusOK).
                End()
+
 }
diff --git a/api/route/route_group_test.go b/api/route/route_group_test.go
deleted file mode 100644
index 702ea79..0000000
--- a/api/route/route_group_test.go
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package route
-
-import (
-       "github.com/apisix/manager-api/conf"
-       "github.com/apisix/manager-api/service"
-       "net/http"
-       "testing"
-)
-
-func TestCreateRouteGroup(t *testing.T) {
-       // create ok
-       handler.
-               Post(uriPrefix+"/routegroups").
-               Header("Authorization", token).
-               JSON(`{
-                       "name": "create_route_group_test",
-                       "description": "test description"
-               }`).
-               Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func TestDuplicateGroupName(t *testing.T) {
-       // duplicate name
-       handler.
-               Post(uriPrefix+"/routegroups").
-               Header("Authorization", token).
-               JSON(`{
-                       "name": "create_route_group_test",
-                       "description": "test description"
-               }`).
-               Expect(t).
-               Status(http.StatusInternalServerError).
-               End()
-}
-
-func TestUpdateRouteGroup(t *testing.T) {
-       routeGroup, _ := getRouteGroupByName("create_route_group_test")
-       //update ok
-       handler.
-               Put(uriPrefix+"/routegroups/"+routeGroup.ID.String()).
-               Header("Authorization", token).
-               JSON(`{
-                       "name": "update_route_group_test",
-                       "description": "test description"
-               }`).
-               Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func TestDeleteRouteGroupHasRoutes(t *testing.T) {
-       routeGroup, _ := getRouteGroupByName("update_route_group_test")
-       // create route
-       handler.Post(uriPrefix+"/routes").
-               Header("Authorization", token).
-               JSON(`{
-                       "name":"api-test-for-delete-group",
-                       "desc":"api-test",
-                       "priority":0,
-                       "protocols":["http"],
-                       "hosts":["test.com"],
-                       "paths":["/*"],
-                       
"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-                       "status":false,
-                       "upstream_protocol":"keep",
-                       "plugins":{},
-                       "uris":["/*"],
-                       "vars":[],
-                       
"upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-                       "timeout":{"connect":6000,"send":6000,"read":6000}},
-                       "upstream_header":{},
-                       "route_group_id":"` + routeGroup.ID.String() + `",
-                       "route_group_name":"` + routeGroup.Name + `"
-}`).Expect(t).
-               Status(http.StatusOK).
-               End()
-       // delete fail
-       handler.
-               Delete(uriPrefix+"/routegroups/"+routeGroup.ID.String()).
-               Header("Authorization", token).
-               Expect(t).
-               Status(http.StatusInternalServerError).
-               End()
-       // get api-test-for-group
-       route, _ := getRouteByName("api-test-for-delete-group")
-       // delete route
-       handler.
-               Delete(uriPrefix+"/routes/"+route.ID.String()).
-               Header("Authorization", token).
-               Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func TestDeleteRouteGroup(t *testing.T) {
-       routeGroup, _ := getRouteGroupByName("update_route_group_test")
-       // delete ok
-       handler.
-               Delete(uriPrefix+"/routegroups/"+routeGroup.ID.String()).
-               Header("Authorization", token).
-               Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func getRouteGroupByName(name string) (*service.RouteGroupDao, error) {
-       db := conf.DB()
-       routeGroup := &service.RouteGroupDao{}
-       if err := db.Table("route_group").Where("name = ?", 
name).First(&routeGroup).Error; err != nil {
-               return nil, err
-       }
-       return routeGroup, nil
-}
diff --git a/api/route/route_test.go b/api/route/route_test.go
deleted file mode 100644
index dff3627..0000000
--- a/api/route/route_test.go
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package route
-
-import (
-       "net/http"
-       "testing"
-
-       "github.com/apisix/manager-api/conf"
-       "github.com/apisix/manager-api/service"
-)
-
-func TestCreateRouteForUngroup(t *testing.T) {
-       // create route with no route group -- test ungroup
-       handler.Post(uriPrefix+"/routes").
-               Header("Authorization", token).
-               JSON(`{
-                       "name":"api-test-no-group",
-                       "desc":"api-test-no-group",
-                       "priority":0,
-                       "protocols":["http"],
-                       "hosts":["test.com"],
-                       "paths":["/*"],
-                       
"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-                       "status":false,
-                       "upstream_protocol":"keep",
-                       "plugins":{},
-                       "uris":["/*"],
-                       "vars":[],
-                       
"upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-                       "timeout":{"connect":6000,"send":6000,"read":6000}},
-                       "upstream_header":{},
-                       "route_group_id":"",
-                       "route_group_name":""
-}`).Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func TestUpdateRouteWithCreateRouteGroup(t *testing.T) {
-       route, _ := getRouteByName("api-test-no-group")
-
-       // update route for create route group
-       handler.Put(uriPrefix+"/routes/"+route.ID.String()).
-               Header("Authorization", token).
-               JSON(`{
-                       "name":"api-test-no-group",
-                       "desc":"api-test-no-group",
-                       "priority":0,
-                       "protocols":["http"],
-                       "hosts":["test.com"],
-                       "paths":["/*"],
-                       
"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-                       "status":false,
-                       "upstream_protocol":"keep",
-                       "plugins":{},
-                       "uris":["/*"],
-                       "vars":[],
-                       
"upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-                       "timeout":{"connect":6000,"send":6000,"read":6000}},
-                       "upstream_header":{},
-                       "route_group_id":"",
-                       "route_group_name":"route-update-test-create-group"
-}`).Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func TestCreateRouteWithCreateNewGroup(t *testing.T) {
-       // create route with new route group
-       handler.Post(uriPrefix+"/routes").
-               Header("Authorization", token).
-               JSON(`{
-                       "name":"api-test-new-group",
-                       "desc":"api-test-new-group",
-                       "priority":0,
-                       "protocols":["http"],
-                       "hosts":["test.com"],
-                       "paths":["/*"],
-                       
"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-                       "status":false,
-                       "upstream_protocol":"keep",
-                       "plugins":{},
-                       "uris":["/*"],
-                       "vars":[],
-                       
"upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-                       "timeout":{"connect":6000,"send":6000,"read":6000}},
-                       "upstream_header":{},
-                       "route_group_id":"",
-                       "route_group_name":"route-create-test-create-group"
-}`).Expect(t).
-               Status(http.StatusOK).
-               End()
-}
-
-func TestCreateRouteWithDuplicateGroupName(t *testing.T) {
-       // create route with duplicate route group name
-       handler.Post(uriPrefix+"/routes").
-               Header("Authorization", token).
-               JSON(`{
-                       "name":"api-test",
-                       "desc":"api-test",
-                       "priority":0,
-                       "protocols":["http"],
-                       "hosts":["test.com"],
-                       "paths":["/*"],
-                       
"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-                       "status":false,
-                       "upstream_protocol":"keep",
-                       "plugins":{},
-                       "uris":["/*"],
-                       "vars":[],
-                       
"upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-                       "timeout":{"connect":6000,"send":6000,"read":6000}},
-                       "upstream_header":{},
-                       "route_group_id":"",
-                       "route_group_name":"route-create-test-create-group"
-}`).Expect(t).
-               Status(http.StatusInternalServerError).
-               End()
-}
-
-func TestPublishRoute(t *testing.T) {
-       // create route
-       handler.Post(uriPrefix+"/routes").
-               Header("Authorization", token).
-               JSON(`{
-      "name":"api-test",
-      "desc":"",
-      "priority":0,
-      "protocols":["http"],
-      "hosts":["test1.com"],
-      "paths":["/*"],
-      "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-      "status":false,
-      "upstream_protocol":"keep",
-      "plugins":{},
-      "uris":["/*"],
-      "vars":[],
-      "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-      "timeout":{"connect":6000,"send":6000,"read":6000}},
-      "upstream_header":{}
-}`).Expect(t).
-               Status(http.StatusOK).
-               End()
-       route, _ := getRouteByName("api-test")
-       // publish route
-       handler.Put(uriPrefix + "/routes/" + route.ID.String() + 
"/publish").Expect(t).Status(http.StatusOK).End()
-}
-
-func TestOfflineRoute(t *testing.T) {
-       // create route
-       handler.Post(uriPrefix+"/routes").
-               Header("Authorization", token).
-               JSON(`{
-      "name":"api-test-published",
-      "desc":"",
-      "priority":0,
-      "protocols":["http"],
-      "hosts":["test1.com"],
-      "paths":["/*"],
-      "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
-      "status":true,
-      "upstream_protocol":"keep",
-      "plugins":{},
-      "uris":["/*"],
-      "vars":[],
-      "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
-      "timeout":{"connect":6000,"send":6000,"read":6000}},
-      "upstream_header":{}
-}`).Expect(t).
-               Status(http.StatusOK).
-               End()
-       routePublished, _ := getRouteByName("api-test-published")
-       // offline route
-       handler.Put(uriPrefix + "/routes/" + routePublished.ID.String() + 
"/offline").Expect(t).Status(http.StatusOK).End()
-}
-
-func getRouteByName(name string) (*service.Route, error) {
-       db := conf.DB()
-       route := &service.Route{}
-       if err := db.Table("routes").Where("name = ?", 
name).First(&route).Error; err != nil {
-               return nil, err
-       }
-       return route, nil
-}
diff --git a/api/route/ssl_test.go b/api/route/ssl_test.go
index 3952b6b..8c85ff3 100644
--- a/api/route/ssl_test.go
+++ b/api/route/ssl_test.go
@@ -22,10 +22,12 @@ import (
 )
 
 func TestSslCreate(t *testing.T) {
+       sslId := "ssl_id"
        // ok
-       handler.
-               Post(uriPrefix + "/ssls").
+       testHandler.
+               Post(uriPrefix + "/ssl").
                JSON(`{
+      "id": "` + sslId + `"
                        "key": "-----BEGIN PRIVATE 
KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGO0J9xrOcmvgh\npkqHIYHCw35FTfIT5uXOSzdF49M2ZAKBQwFG0ovYT8bc0glNLB+hpDhJPL531qSP\nl1ZOe0W1ofP1u0T5Zzc9Rub/kn7RMPq0BsSC6J3rF+rQEwh1PM8qUuD8DxZ7jaOL\niMNL6SyuZIPsS1kPPBtsioukdo666tbjNMixhQbI9Wpg55abdXRFh3i7Zu/9siF1\njCGcsskjOaUOY4sYQ3i5WU/HIIRhA82XuIL+Sxd32P8bKi2UT1sqFXRjAVR7KRWo\nIVvkmSLoZb9ucV6MsccDrRYBf6rLbI1tFj9l2rY6GTFlT+6z7K/ZI60DGi/hsBfl\nDeEQ5WuxAgMBAAECggEAVHQQyucpxHGdfzCKlfGnh+Oj20Du/p2jkHUp
 [...]
                        "cert": "-----BEGIN 
CERTIFICATE-----\nMIIEVzCCAr+gAwIBAgIQITiNM7xmudhg3pK85KDwLDANBgkqhkiG9w0BAQsFADB/\nMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExKjAoBgNVBAsMIWp1bnh1\nY2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTExMC8GA1UEAwwobWtjZXJ0IGp1\nbnh1Y2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTAeFw0xOTA2MDEwMDAwMDBa\nFw0zMDA3MDgwNzQ4MDJaMFUxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBj\nZXJ0aWZpY2F0ZTEqMCgGA1UECwwhanVueHVjaGVuQGp1bnh1ZGVBaXIgKGp1bnh1\nIGNoZW4pMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjt
 [...]
                }`).
@@ -33,25 +35,31 @@ func TestSslCreate(t *testing.T) {
                Status(http.StatusOK).
                End()
 
-       // schema fail
-       handler.
-               Post(uriPrefix + "/ssls").
+       //update ok
+       testHandler.
+               Put(uriPrefix + "/consumers/" + sslId).
                JSON(`{
+      "id": "` + sslId + `"
+                       "key": "-----BEGIN PRIVATE 
KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGO0J9xrOcmvgh\npkqHIYHCw35FTfIT5uXOSzdF49M2ZAKBQwFG0ovYT8bc0glNLB+hpDhJPL531qSP\nl1ZOe0W1ofP1u0T5Zzc9Rub/kn7RMPq0BsSC6J3rF+rQEwh1PM8qUuD8DxZ7jaOL\niMNL6SyuZIPsS1kPPBtsioukdo666tbjNMixhQbI9Wpg55abdXRFh3i7Zu/9siF1\njCGcsskjOaUOY4sYQ3i5WU/HIIRhA82XuIL+Sxd32P8bKi2UT1sqFXRjAVR7KRWo\nIVvkmSLoZb9ucV6MsccDrRYBf6rLbI1tFj9l2rY6GTFlT+6z7K/ZI60DGi/hsBfl\nDeEQ5WuxAgMBAAECggEAVHQQyucpxHGdfzCKlfGnh+Oj20Du/p2jkHUp
 [...]
                        "cert": "-----BEGIN 
CERTIFICATE-----\nMIIEVzCCAr+gAwIBAgIQITiNM7xmudhg3pK85KDwLDANBgkqhkiG9w0BAQsFADB/\nMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExKjAoBgNVBAsMIWp1bnh1\nY2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTExMC8GA1UEAwwobWtjZXJ0IGp1\nbnh1Y2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTAeFw0xOTA2MDEwMDAwMDBa\nFw0zMDA3MDgwNzQ4MDJaMFUxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBj\nZXJ0aWZpY2F0ZTEqMCgGA1UECwwhanVueHVjaGVuQGp1bnh1ZGVBaXIgKGp1bnh1\nIGNoZW4pMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjt
 [...]
                }`).
                Expect(t).
-               Status(http.StatusBadRequest).
+               Status(http.StatusOK).
                End()
 
-       //schema fail 2
-       handler.
-               Post(uriPrefix + "/ssls").
-               JSON(`{
-                       "key": "",
-                       "cert": "-----BEGIN 
CERTIFICATE-----\nMIIEVzCCAr+gAwIBAgIQITiNM7xmudhg3pK85KDwLDANBgkqhkiG9w0BAQsFADB/\nMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExKjAoBgNVBAsMIWp1bnh1\nY2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTExMC8GA1UEAwwobWtjZXJ0IGp1\nbnh1Y2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTAeFw0xOTA2MDEwMDAwMDBa\nFw0zMDA3MDgwNzQ4MDJaMFUxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBj\nZXJ0aWZpY2F0ZTEqMCgGA1UECwwhanVueHVjaGVuQGp1bnh1ZGVBaXIgKGp1bnh1\nIGNoZW4pMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjt
 [...]
-               }`).
+       //list
+       testHandler.
+               Get(uriPrefix + "/ssl").
+               Headers(map[string]string{"Authorization": token}).
                Expect(t).
-               Status(http.StatusBadRequest).
+               Status(http.StatusOK).
+               End()
+
+       //delete
+       testHandler.
+               Delete(uriPrefix + "/consumers/" + sslId).
+               Expect(t).
+               Status(http.StatusOK).
                End()
 
 }
diff --git a/api/route/zclear_test.go b/api/route/zclear_test.go
deleted file mode 100644
index e44101b..0000000
--- a/api/route/zclear_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package route
-
-import (
-       "net/http"
-       "testing"
-
-       "github.com/apisix/manager-api/service"
-)
-
-func TestClearTestData(t *testing.T) {
-       // delete consumers
-       c1, _ := service.GetConsumerByUserName("e2e_test_consumer1")
-       handler.
-               Delete(uriPrefix + "/consumers/" + c1.ID.String()).
-               Expect(t).
-               Status(http.StatusOK).
-               End()
-
-       //delete test ssl
-       service.DeleteTestSslData()
-}
diff --git a/api/service/base_test.go b/api/service/base_test.go
deleted file mode 100644
index dc665a9..0000000
--- a/api/service/base_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package service
-
-import (
-       "github.com/apisix/manager-api/conf"
-)
-
-func init() {
-       conf.InitializeMysql()
-}
diff --git a/api/service/consumer_test.go b/api/service/consumer_test.go
deleted file mode 100644
index cd0e3d9..0000000
--- a/api/service/consumer_test.go
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package service
-
-import (
-       "testing"
-
-       "github.com/apisix/manager-api/errno"
-       uuid "github.com/satori/go.uuid"
-       "github.com/stretchr/testify/assert"
-)
-
-var (
-       c1 = uuid.NewV4()
-       c2 = uuid.NewV4()
-)
-
-func TestConsumerCurd(t *testing.T) {
-       //test3.com
-       param := []byte(`{
-       "username": "test_consumer",
-    "plugins": {
-        "key-auth": {
-            "key": "auth-one"
-        },
-        "limit-count": {
-            "count": 2,
-            "time_window": 60,
-            "rejected_code": 503,
-            "key": "remote_addr"
-        }
-    },
-       "desc": "test description"
-}`)
-
-       err := ConsumerCreate(param, c1.String())
-
-       assert := assert.New(t)
-       assert.Nil(err)
-
-       //get item
-       consumer, err := ConsumerItem(c1.String())
-       assert.Nil(err)
-       assert.Equal("test_consumer", consumer.Username)
-       assert.Equal(2, len(consumer.Plugins))
-
-       //duplicate username fail
-       param = []byte(`{
-       "username": "test_consumer",
-    "plugins": {
-        "key-auth": {
-            "key": "auth-one"
-        },
-        "limit-count": {
-            "count": 2,
-            "time_window": 60,
-            "rejected_code": 503,
-            "key": "remote_addr"
-        }
-    },
-       "desc": "test description"
-}`)
-
-       err = ConsumerCreate(param, c2.String())
-       assert.NotNil(err)
-       assert.Equal(errno.DuplicateUserName.Code, 
err.(*errno.ManagerError).Code)
-
-       // ok
-       param = []byte(`{
-       "username": "test_consumer2",
-    "plugins": {
-        "key-auth": {
-            "key": "auth-one"
-        }
-    },
-       "desc": "test description2"
-}`)
-
-       err = ConsumerCreate(param, c2.String())
-       assert.Nil(err)
-
-       //list
-       count, list, err := ConsumerList(2, 1, "")
-       assert.Equal(true, count >= 2)
-       assert.Equal(1, len(list))
-
-       //update
-       param = []byte(`{
-       "username": "test_consumer1",
-    "plugins": {
-        "key-auth": {
-            "key": "auth-one"
-        },
-        "limit-count": {
-            "count": 2,
-            "time_window": 60,
-            "rejected_code": 503,
-            "key": "remote_addr"
-        }
-    },
-       "desc": "test description"
-}`)
-
-       err = ConsumerUpdate(param, c1.String())
-       assert.Nil(err)
-
-       consumer, _ = ConsumerItem(c1.String())
-       assert.Equal("test_consumer1", consumer.Username)
-
-       //delete
-       err = ConsumerDelete(c1.String())
-       assert.Nil(err)
-
-       _, err = ConsumerItem(c1.String())
-       assert.Equal(errno.DBReadError.Code, err.(*errno.ManagerError).Code)
-
-       err = ConsumerDelete(c2.String())
-       assert.Nil(err)
-}
diff --git a/api/service/route_group_test.go b/api/service/route_group_test.go
deleted file mode 100644
index cb656b3..0000000
--- a/api/service/route_group_test.go
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package service
-
-import (
-       "testing"
-
-       uuid "github.com/satori/go.uuid"
-       "github.com/stretchr/testify/assert"
-)
-
-var gid = uuid.NewV4()
-var gid2 = uuid.NewV4()
-
-func TestCreateRouteGroup(t *testing.T) {
-       routeGroup := &RouteGroupDao{
-               Base:        Base{},
-               Name:        "route_group_test",
-               Description: "route_group_test",
-       }
-       routeGroup.ID = gid
-       // create ok
-       err := routeGroup.CreateRouteGroup()
-       as := assert.New(t)
-       as.Nil(err)
-}
-
-func TestGetRouteGroup(t *testing.T) {
-       // get group ok
-       as := assert.New(t)
-       getGroup := &RouteGroupDao{}
-       err, i := getGroup.FindRouteGroup(gid.String())
-       as.Nil(err)
-       as.Equal("route_group_test", getGroup.Name)
-       as.Equal(1, i)
-}
-
-func TestRouteGroupNameDuplicate(t *testing.T) {
-       // name duplicate
-       as := assert.New(t)
-       routeGroup2 := &RouteGroupDao{
-               Base:        Base{},
-               Name:        "route_group_test",
-               Description: "route_group_test",
-       }
-       routeGroup2.ID = gid2
-       err := routeGroup2.CreateRouteGroup()
-       as.NotNil(err)
-       // ok
-       routeGroup2.Name = "route_group_test2"
-       err = routeGroup2.CreateRouteGroup()
-       as.Nil(err)
-}
-
-func TestGetRouteGupList(t *testing.T) {
-       as := assert.New(t)
-       // list ok
-       routeGroups := []RouteGroupDao{}
-       routeGroup := &RouteGroupDao{}
-       err, i3 := routeGroup.GetRouteGroupList(&routeGroups, "", 1, 2)
-       as.Nil(err)
-       as.Equal(true, i3 >= 2)
-       as.Equal(2, len(routeGroups))
-}
-
-func TestUpdateRouteGroup(t *testing.T) {
-       as := assert.New(t)
-       // update ok
-       routeGroup := &RouteGroupDao{
-               Base:        Base{},
-               Name:        "route_group_test_update",
-               Description: "route_group_test_update",
-       }
-       routeGroup.ID = gid
-       err := routeGroup.UpdateRouteGroup()
-       as.Nil(err)
-}
-
-func TestDeleteRouteGroup(t *testing.T) {
-       as := assert.New(t)
-       routeGroup := &RouteGroupDao{
-               Base:        Base{},
-               Name:        "route_group_test_update",
-               Description: "route_group_test_update",
-       }
-       routeGroup.ID = gid
-       // delete ok
-       err := routeGroup.DeleteRouteGroup()
-       as.Nil(err)
-
-       deleteGroup := &RouteGroupDao{}
-       err, i2 := deleteGroup.FindRouteGroup(gid.String())
-       as.Nil(err)
-       as.Equal("", deleteGroup.Name)
-       as.Equal(0, i2)
-
-       routeGroup2 := &RouteGroupDao{
-               Base:        Base{},
-               Name:        "route_group_test",
-               Description: "route_group_test",
-       }
-       routeGroup2.ID = gid2
-       err = routeGroup2.DeleteRouteGroup()
-       as.Nil(err)
-}
diff --git a/api/service/route_test.go b/api/service/route_test.go
deleted file mode 100644
index 98bf3e0..0000000
--- a/api/service/route_test.go
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package service
-
-import (
-       "encoding/json"
-       "testing"
-
-       uuid "github.com/satori/go.uuid"
-       "github.com/stretchr/testify/assert"
-)
-
-func TestRedirectMarshal(t *testing.T) {
-       a := assert.New(t)
-       r := &Redirect{
-               HttpToHttps: true,
-               Code:        302,
-               Uri:         "/hello",
-       }
-       if result, err := json.Marshal(r); err != nil {
-               t.Error(err.Error())
-       } else {
-               h := make(map[string]interface{})
-               json.Unmarshal(result, &h)
-               a.Equal(1, len(h))
-               a.Equal(nil, h["code"])
-               a.Equal(true, h["http_to_https"])
-       }
-}
-
-func TestToApisixRequest_RediretPlugins(t *testing.T) {
-       rr := &RouteRequest{
-               ID:        "u guess a uuid",
-               Name:      "a special name",
-               Desc:      "any description",
-               Priority:  0,
-               Methods:   []string{"GET"},
-               Uris:      []string{},
-               Hosts:     []string{"www.baidu.com"},
-               Protocols: []string{"http", "https", "websocket"},
-               Redirect:  &Redirect{HttpToHttps: true, Code: 200, Uri: 
"/hello"},
-               Vars:      [][]string{},
-       }
-       ar := ToApisixRequest(rr)
-       a := assert.New(t)
-       a.Equal(1, len(ar.Plugins))
-       a.NotEqual(nil, ar.Plugins["redirect"])
-}
-
-func TestToApisixRequest_proxyRewrite(t *testing.T) {
-       nodes := make(map[string]int64)
-       nodes["127.0.0.1:8080"] = 100
-       upstream := &Upstream{
-               UType:   "roundrobin",
-               Nodes:   nodes,
-               Timeout: UpstreamTimeout{15, 15, 15},
-       }
-       to := "/hello"
-       upstreamPath := &UpstreamPath{To: to}
-       rr := &RouteRequest{
-               ID:           "u guess a uuid",
-               Name:         "a special name",
-               Desc:         "any description",
-               Priority:     0,
-               Methods:      []string{"GET"},
-               Uris:         []string{},
-               Hosts:        []string{"www.baidu.com"},
-               Protocols:    []string{"http", "https", "websocket"},
-               Redirect:     &Redirect{HttpToHttps: true, Code: 200, Uri: 
"/hello"},
-               Vars:         [][]string{},
-               Upstream:     upstream,
-               UpstreamPath: upstreamPath,
-       }
-       ar := ToApisixRequest(rr)
-       a := assert.New(t)
-       var pr ProxyRewrite
-       bytes, _ := json.Marshal(ar.Plugins["proxy-rewrite"])
-       json.Unmarshal(bytes, &pr)
-
-       a.Equal(2, len(ar.Plugins))
-       a.NotEqual(nil, ar.Plugins["redirect"])
-       a.Equal(to, pr.Uri)
-}
-
-func TestToApisixRequest_Vars(t *testing.T) {
-       rr := &RouteRequest{
-               ID:        "u guess a uuid",
-               Name:      "a special name",
-               Desc:      "any description",
-               Priority:  0,
-               Methods:   []string{"GET"},
-               Uris:      []string{},
-               Hosts:     []string{"www.baidu.com"},
-               Protocols: []string{"http", "https", "websocket"},
-               Redirect:  &Redirect{HttpToHttps: true, Code: 200, Uri: 
"/hello"},
-               Vars:      [][]string{},
-       }
-       ar := ToApisixRequest(rr)
-       a := assert.New(t)
-       b, err := json.Marshal(ar)
-       a.Equal(nil, err)
-
-       m := make(map[string]interface{})
-       err = json.Unmarshal(b, &m)
-       a.Equal(nil, err)
-       t.Log(m["vars"])
-       a.Equal(nil, m["vars"])
-}
-
-func TestToApisixRequest_Upstream(t *testing.T) {
-       nodes := make(map[string]int64)
-       nodes["127.0.0.1:8080"] = 100
-       upstream := &Upstream{
-               UType:   "roundrobin",
-               Nodes:   nodes,
-               Timeout: UpstreamTimeout{15, 15, 15},
-       }
-       rr := &RouteRequest{
-               ID:        "u guess a uuid",
-               Name:      "a special name",
-               Desc:      "any description",
-               Priority:  0,
-               Methods:   []string{"GET"},
-               Uris:      []string{},
-               Hosts:     []string{"www.baidu.com"},
-               Protocols: []string{"http", "https", "websocket"},
-               Redirect:  &Redirect{HttpToHttps: true, Code: 200, Uri: 
"/hello"},
-               Vars:      [][]string{},
-               Upstream:  upstream,
-       }
-       ar := ToApisixRequest(rr)
-       a := assert.New(t)
-       a.Equal("roundrobin", ar.Upstream.UType)
-       a.Equal(true, ar.Upstream.EnableWebsocket)
-}
-
-func TestToApisixRequest_UpstreamUnable(t *testing.T) {
-       nodes := make(map[string]int64)
-       nodes["127.0.0.1:8080"] = 100
-       upstream := &Upstream{
-               UType:   "roundrobin",
-               Nodes:   nodes,
-               Timeout: UpstreamTimeout{15, 15, 15},
-       }
-       rr := &RouteRequest{
-               ID:        "u guess a uuid",
-               Name:      "a special name",
-               Desc:      "any description",
-               Priority:  0,
-               Methods:   []string{"GET"},
-               Uris:      []string{},
-               Hosts:     []string{"www.baidu.com"},
-               Protocols: []string{"http", "https"},
-               Redirect:  &Redirect{HttpToHttps: true, Code: 200, Uri: 
"/hello"},
-               Vars:      [][]string{},
-               Upstream:  upstream,
-       }
-       ar := ToApisixRequest(rr)
-       a := assert.New(t)
-       a.Equal("roundrobin", ar.Upstream.UType)
-       a.Equal(false, ar.Upstream.EnableWebsocket)
-}
-
-// no upstream
-func TestApisixRouteResponse_Parse(t *testing.T) {
-       a := assert.New(t)
-       plugins := make(map[string]interface{})
-       redirect := &Redirect{
-               Code: 302,
-               Uri:  "/foo",
-       }
-       plugins["redirect"] = redirect
-       arr := &ApisixRouteResponse{
-               Action: "get",
-               Node: &Node{
-                       Value: Value{
-                               Id:       "",
-                               Name:     "",
-                               Desc:     "",
-                               Priority: 0,
-                               Methods:  []string{"GET"},
-                               Uris:     []string{"/*"},
-                               Hosts:    []string{"www.baidu.com"},
-                               Vars:     [][]string{},
-                               Upstream: nil,
-                               Plugins:  plugins,
-                       },
-               },
-       }
-       _, err := arr.Parse()
-       a.Equal(nil, err)
-}
-
-// parse from params to RouteRequest
-func TestRouteRequest_Parse(t *testing.T) {
-       a := assert.New(t)
-       param := []byte(`{
-                "name": "API 名称",
-                "protocols": [
-                        "http",
-                        "https"
-                ],
-                "hosts": [
-                        "www.baidu.com"
-                ],
-                "methods": [
-                        "GET",
-                        "HEAD",
-                        "POST",
-                        "PUT",
-                        "DELETE",
-                        "OPTIONS",
-                        "PATCH"
-                ],
-                "redirect": {
-                        "code": 302,
-                        "uri": "11111"
-                },
-                "vars": [],
-                "script": {
-                        "rule": {},
-                        "conf": {}
-                }
-        }`)
-       routeRequest := &RouteRequest{}
-       err := routeRequest.Parse(param)
-       a.Nil(err)
-       a.Equal("API 名称", routeRequest.Name)
-       a.Equal(int64(0), routeRequest.Priority)
-       a.Equal(2, len(routeRequest.Script))
-       a.Equal("/*", routeRequest.Uris[0])
-}
-
-// parse from RouteRequest and ApisixRouteRequest to Route
-func TestRoute_Parse(t *testing.T) {
-       a := assert.New(t)
-       rrb := []byte(`{"name":"API 
名称2","methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],"uris":["/*"],"hosts":["www.baidu.com"],"protocols":["http","https"],"redirect":{"code":302,"uri":"11111"},"plugins":null}`)
-       routeRequest := &RouteRequest{}
-       json.Unmarshal(rrb, routeRequest)
-       arrb := 
[]byte(`{"priority":0,"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],"uris":["/*"],"hosts":["www.baidu.com"],"plugins":{"redirect":{"code":302,"uri":"11111"}},
 "script":{
-    "rule":{
-        "root": "11-22-33-44",
-        "11-22-33-44":[
-            [
-                "code == 503",
-                "yy-uu-ii-oo"
-            ],
-            [
-                "",
-                "vv-cc-xx-zz"
-            ]
-        ]
-    },
-    "conf":{
-        "11-22-33-44":{
-            "name": "limit-count",
-            "conf": {
-                "count":2,
-                "time_window":60,
-                "rejected_code":503,
-                "key":"remote_addr"
-            }
-        },
-        "yy-uu-ii-oo":{
-            "name": "response-rewrite",
-            "conf": {
-                "body":{"code":"ok","message":"request has been limited."},
-                "headers":{
-                    "X-limit-status": "limited"
-                }
-            }
-        },
-        "vv-cc-xx-zz":{
-            "name": "response-rewrite",
-            "conf": {
-                "body":{"code":"ok","message":"normal request"},
-                "headers":{
-                    "X-limit-status": "normal"
-                }
-            }
-        }
-    }
-} }`)
-       arr := &ApisixRouteRequest{}
-       json.Unmarshal(arrb, arr)
-
-       rd := &Route{}
-       err := rd.Parse(routeRequest, arr)
-       a.Nil(err)
-}
-
-// parse Route
-func TestToRoute(t *testing.T) {
-       a := assert.New(t)
-       b1 := []byte(`{"name":"API 
名称2","methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],"uris":["/*"],"hosts":["www.baidu.com"],"protocols":["http","https"],"redirect":{"code":302,"uri":"11111"},"plugins":null}`)
-       rr := &RouteRequest{}
-       err := json.Unmarshal(b1, &rr)
-       a.Nil(err)
-
-       b2 := 
[]byte(`{"priority":0,"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],"uris":["/*"],"hosts":["www.baidu.com"],"plugins":{"redirect":{"code":302,"uri":"11111"}},"script":"function(vars,
 opts) return vars[\"arg_key\"] == \"a\" or vars[\"arg_key\"] == \"b\" end"}`)
-       arr := &ApisixRouteRequest{}
-       err = json.Unmarshal(b2, &arr)
-       a.Nil(err)
-
-       b3 := 
[]byte(`{"action":"set","node":{"value":{"id":"","name":"","priority":0,"methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],"uris":["/*"],"hosts":["www.baidu.com"],"vars":null,"plugins":{"redirect":{"code":302,"ret_code":302,"uri":"11111"}}},"modifiedIndex":75}}`)
-       arp := &ApisixRouteResponse{}
-       err = json.Unmarshal(b3, &arp)
-       a.Nil(err)
-
-       u4 := uuid.NewV4()
-       route, err := ToRoute(rr, arr, u4, arp)
-       a.Nil(err)
-       t.Log(route.Uris)
-       a.Equal("[\"/*\"]", route.Uris)
-}
diff --git a/api/service/ssl_test.go b/api/service/ssl_test.go
deleted file mode 100644
index 2134bb1..0000000
--- a/api/service/ssl_test.go
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package service
-
-import (
-       "strings"
-       "testing"
-
-       "github.com/apisix/manager-api/errno"
-       uuid "github.com/satori/go.uuid"
-       "github.com/stretchr/testify/assert"
-)
-
-var (
-       u1 = uuid.NewV4()
-       u2 = uuid.NewV4()
-)
-
-func TestSslParseCert(t *testing.T) {
-       ssl, err := ParseCert("", "")
-
-       assert := assert.New(t)
-       assert.Nil(ssl)
-       assert.Equal("invalid certificate", err.Error())
-
-       //KeyPair fail
-
-       cert := `-----BEGIN CERTIFICATE-----
-MIIEWjCCAsKgAwIBAgIRAMLLNCKEvgEQL22Hpox6E1kwDQYJKoZIhvcNAQELBQAw
-fzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSowKAYDVQQLDCFqdW54
-dWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikxMTAvBgNVBAMMKG1rY2VydCBq
-dW54dWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikwHhcNMTkwNjAxMDAwMDAw
-WhcNMzAwNjA5MTA0MjA1WjBVMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQg
-Y2VydGlmaWNhdGUxKjAoBgNVBAsMIWp1bnh1Y2hlbkBqdW54dWRlQWlyIChqdW54
-dSBjaGVuKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2lg+vzHkRI
-Cs8PHv6UVxXFbrL6wlsdurOICkW5daKUJyzUZQZl11CK9SWOk8vAc7j3pQ7Mz15r
-hfQB558WHzI/XXbZ1NrZrTpLaL0fWW5n4hIE8EbYf3Hy/xM8gRUXsWMEexq2WC/R
-PfTCQIZ85vUSANS72E5rHdba3Y5IMr8bn/NUg1sm2LxZQmZV6tBOpYnibyj7bXxw
-8kxr4w+B/5jDBPmwL59bdoatEs1FjdHzz+fbW1K4NdHZZEotYqkQhCS09JnwGswd
-Ariy+Is44kt/gtw7nVWmuV/eQaxPEHVE4Bwvdmv11IsPsj6hif23gXjXLIHx66CY
-/S4I/P0allkCAwEAAaN7MHkwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG
-AQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUVPhGyY/h6etoAqzb298k
-JGJzx1wwIwYDVR0RBBwwGoIJdGVzdDMuY29tgg13d3cudGVzdDMuY29tMA0GCSqG
-SIb3DQEBCwUAA4IBgQCgb5wOMzkD1/tgrjwE7Cj1NvX7/p/JIQVVtvtnnypyXGNn
-VL+q4oB9WzvOvMcTCiKKHqg9jCiu/KFFHy7nRzj7KPhU/o9M7qLNwLJjfUOtPYUm
-rS62kEXlj5L5+UJjiGABGfLllxMwwTkAFbdSUSB1awzoafPn5+g+qABXgkF/EN2I
-+IJcJCqg3IO30n4MMhqNx3IbqIohD3p5GzjQqnuQSrC/HJEsUuIlMCHPJ1GVbbrd
-RnSySMcbv2jThP53JVIe+0HHvcujb2pDQ4RcCSaN3OXaZDYVqoSR04+amotGwiWO
-DY/4LTWFJkfoWnv1kg2/AllMpsXB+1u+O+x6qWzBw2hXP5AM+8KIoJ2/Mb13TsN9
-qhrGep+SfhjARH068ZjaS2zQC2Uvc+SrEGXfITPIkstRELxIV9Lmjl9lwpAOJrte
-4TDjYhBS20j6mt3dUyEBnPfkpcOeLYZNS1sK66MRfzJ9MowdTcWyvMzFHjSjfWPY
-+4scQdmkFkCulnzylak=
------END CERTIFICATE-----`
-       key := `-----BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC25tQs8GRxdWUR
-c4kjhmJmrxQgCcoN4VTHyBbdbnZFPgxCULAr/2e54ooatMWh9DEdrgpi3EfQXqDV
-okzKrSfJVZqmS1qOcgaSkgz5/puKcF31bXUgSVw1qGEjXbpQcyzZp95pPaErXCq3
-7bKST5d0TO8asNebON+jZZkpa5NA+qFOOWdx0Y6UWG0G/RzhYyRRU9B6+SBwOLa8
-c9+07vxjjAOXfr5Terp0lS9xNOVcjnHA48XPq2y8cJstbVjQI8Ls1HlzJoeJz+lt
-FFxd8nMQ30NoJYoVXewUEjuTibQdEpUY8m5zuNqYKOax4McpoTouKl2BWIuWr10Y
-Wrtw9XWlAgMBAAECggEAdoDsbAl9Kr3jNAFlk2zYiKtbIL72+TNL2P1dQy701jwz
-eSwKWRdsP1X2IQOLITm0MQS4mgEbTnhhQMmdc5vpMVuTjbc4/x4GACU83yUF5haT
-6hZ3Uun1IpbsCRwLQWC+aG+JfSp/KDbZPr51erKy8JmAOgzmRR3+WEHVkK6wg+JF
-qDha7Gnq2xgzmutGLBUb9BFgL7bbNyf3V4d+HbgYPjQossfpLnTIrsmKce36r5U8
-pF6Uf69EUs34N9w98E6mEGY12nY4jOKZMeRPR1FIGGK7Y3+7fkd2+pYF00s7uSUq
-/j8DdxxykqvZkE1lBZJBwxk9Ty4PBq2lNKdq6pXtAQKBgQDu12vVuenRCJEsK2FY
-puYlfoDiQpIYzK9Bme+eDsPcVyOQ9q+Tf4QASZN81InQsanQ2ovcbmSpB52/ZvjU
-rVX7RnIEcZ6jB1VUcCU/QOEg0kqTkCo3SfyeawF8iPyuLSbb5ZBufFMq6nOyOWco
-hg4EqQIg3rcKw3lW8NT6DqqRxQKBgQDECpuhfEMYUslfDlSbS8V/vSXjD2xzRFt3
-SL87xQXwZOLRPYiLdRGb/WP2L/PGE8K1XUMz/geeFeAdrzRxJ1JtCn/K0UyMxSnw
-TJEm6CFfsOJXOq4yC5gosNYw3xBc9NKtsGLrAlWOBLPdeO1wdrM6BYfs6AP3X49r
-67Y7AujyYQKBgQCMSV//c2nQ6/VJOlm9VprL3xgYzf0+L8uo/p/t+MI2Q8CSPzM1
-sap4+L52jeg8+n3CPPv1h6n8Vorjh7oUQZPFOcVyssH5BC+snwphstwJCTvgnMcP
-HpgQ/M0sttGkBMVUV+yT2NaI2JkIUAs1lDfbqOGlKOvemJ5G4MJX9hFd+QKBgQDC
-oe2F1EMg4QCAWU/yprW8buQwnF2FyzYsJZOHGcMdumveZYMtQdtrzZTzFQSngXLs
-cV2JPwn9D6bkkdA1D18sVyItEMM5d359zubFg+2ufYUaKW5MzWoR7A+bkbtDLuYD
-/30V6clbKJwSpD7IS3EBiAA9WtSlQsC32tuflvIDwQKBgAqJAqrempkVGA2rvTX5
-7uWCAiqUKX859kmIuQV9RTQ7qfQRWhckuAjeTdTq6tWKFkzaVaRCXb+tRi7eqVsz
-R/us0LXwHez2LacSVudO7g/LMY3yDxVL2iFLVA/x1FBqjAgjWAEfnc7PmZSK2B3g
-fpf+iWh15t6I4nuyEmMFmtVr
------END PRIVATE KEY-----`
-       ssl1, err := ParseCert(cert, key)
-
-       assert.Nil(ssl1)
-       assert.Equal("key and cert don't match", err.Error())
-
-       // ip
-
-       cert = `-----BEGIN CERTIFICATE-----
-MIIERjCCAq6gAwIBAgIRALI5vYiIHdtNd4ocLsZ9i/IwDQYJKoZIhvcNAQELBQAw
-fzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSowKAYDVQQLDCFqdW54
-dWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikxMTAvBgNVBAMMKG1rY2VydCBq
-dW54dWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikwHhcNMTkwNjAxMDAwMDAw
-WhcNMzAwNjAzMDEyODQ5WjBVMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQg
-Y2VydGlmaWNhdGUxKjAoBgNVBAsMIWp1bnh1Y2hlbkBqdW54dWRlQWlyIChqdW54
-dSBjaGVuKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALbm1CzwZHF1
-ZRFziSOGYmavFCAJyg3hVMfIFt1udkU+DEJQsCv/Z7niihq0xaH0MR2uCmLcR9Be
-oNWiTMqtJ8lVmqZLWo5yBpKSDPn+m4pwXfVtdSBJXDWoYSNdulBzLNmn3mk9oStc
-KrftspJPl3RM7xqw15s436NlmSlrk0D6oU45Z3HRjpRYbQb9HOFjJFFT0Hr5IHA4
-trxz37Tu/GOMA5d+vlN6unSVL3E05VyOccDjxc+rbLxwmy1tWNAjwuzUeXMmh4nP
-6W0UXF3ycxDfQ2glihVd7BQSO5OJtB0SlRjybnO42pgo5rHgxymhOi4qXYFYi5av
-XRhau3D1daUCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG
-AQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUVPhGyY/h6etoAqzb298k
-JGJzx1wwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAYEAowBgpVs+
-pZ4PeT2mVx79thwh02AzinmNbMQMboHK9RaRSZHxLHiVjY7LR1qn5zjLcUcZHel7
-96bka6vlufYzWHSjtKwAchDVVPVK6tzpfHnpLzNLShx0LjIl0EvjrHv5mHIx8R1T
-WKQGxwdTzIxGMgrziuTNc1LvS+yoJElWe07PeRSdSPKUNKQQWqaukzqw3JZaLQkm
-8MaqrzQwNEsCbeojz/ME3e+SzpSsqXgW0x5Og4TyEnIen/q7OzmRzrkHR40Hu+j4
-aW287l3ywIU0pGl/sY2bmyOYCgpZ5w2utfdd7167Doy4vHFKJD3GuN3i+W1f7PyF
-gdUFUQTr6HO4sfQXeZoitzl2Dvr360sb9BBDLAoFiV6J5bAV4algVz45kSpJ7VIm
-pfS8+BUcZHWbn35M9mx2dyoNvIajcET545D60wcttqw4TRh4ljsE69GCU1swiwxH
-hXSkf958injuwYuxv0b1k9qGm6znJc+tRcn35H6x0ff/HwuBIj3TsEXo
------END CERTIFICATE-----`
-       key = `-----BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC25tQs8GRxdWUR
-c4kjhmJmrxQgCcoN4VTHyBbdbnZFPgxCULAr/2e54ooatMWh9DEdrgpi3EfQXqDV
-okzKrSfJVZqmS1qOcgaSkgz5/puKcF31bXUgSVw1qGEjXbpQcyzZp95pPaErXCq3
-7bKST5d0TO8asNebON+jZZkpa5NA+qFOOWdx0Y6UWG0G/RzhYyRRU9B6+SBwOLa8
-c9+07vxjjAOXfr5Terp0lS9xNOVcjnHA48XPq2y8cJstbVjQI8Ls1HlzJoeJz+lt
-FFxd8nMQ30NoJYoVXewUEjuTibQdEpUY8m5zuNqYKOax4McpoTouKl2BWIuWr10Y
-Wrtw9XWlAgMBAAECggEAdoDsbAl9Kr3jNAFlk2zYiKtbIL72+TNL2P1dQy701jwz
-eSwKWRdsP1X2IQOLITm0MQS4mgEbTnhhQMmdc5vpMVuTjbc4/x4GACU83yUF5haT
-6hZ3Uun1IpbsCRwLQWC+aG+JfSp/KDbZPr51erKy8JmAOgzmRR3+WEHVkK6wg+JF
-qDha7Gnq2xgzmutGLBUb9BFgL7bbNyf3V4d+HbgYPjQossfpLnTIrsmKce36r5U8
-pF6Uf69EUs34N9w98E6mEGY12nY4jOKZMeRPR1FIGGK7Y3+7fkd2+pYF00s7uSUq
-/j8DdxxykqvZkE1lBZJBwxk9Ty4PBq2lNKdq6pXtAQKBgQDu12vVuenRCJEsK2FY
-puYlfoDiQpIYzK9Bme+eDsPcVyOQ9q+Tf4QASZN81InQsanQ2ovcbmSpB52/ZvjU
-rVX7RnIEcZ6jB1VUcCU/QOEg0kqTkCo3SfyeawF8iPyuLSbb5ZBufFMq6nOyOWco
-hg4EqQIg3rcKw3lW8NT6DqqRxQKBgQDECpuhfEMYUslfDlSbS8V/vSXjD2xzRFt3
-SL87xQXwZOLRPYiLdRGb/WP2L/PGE8K1XUMz/geeFeAdrzRxJ1JtCn/K0UyMxSnw
-TJEm6CFfsOJXOq4yC5gosNYw3xBc9NKtsGLrAlWOBLPdeO1wdrM6BYfs6AP3X49r
-67Y7AujyYQKBgQCMSV//c2nQ6/VJOlm9VprL3xgYzf0+L8uo/p/t+MI2Q8CSPzM1
-sap4+L52jeg8+n3CPPv1h6n8Vorjh7oUQZPFOcVyssH5BC+snwphstwJCTvgnMcP
-HpgQ/M0sttGkBMVUV+yT2NaI2JkIUAs1lDfbqOGlKOvemJ5G4MJX9hFd+QKBgQDC
-oe2F1EMg4QCAWU/yprW8buQwnF2FyzYsJZOHGcMdumveZYMtQdtrzZTzFQSngXLs
-cV2JPwn9D6bkkdA1D18sVyItEMM5d359zubFg+2ufYUaKW5MzWoR7A+bkbtDLuYD
-/30V6clbKJwSpD7IS3EBiAA9WtSlQsC32tuflvIDwQKBgAqJAqrempkVGA2rvTX5
-7uWCAiqUKX859kmIuQV9RTQ7qfQRWhckuAjeTdTq6tWKFkzaVaRCXb+tRi7eqVsz
-R/us0LXwHez2LacSVudO7g/LMY3yDxVL2iFLVA/x1FBqjAgjWAEfnc7PmZSK2B3g
-fpf+iWh15t6I4nuyEmMFmtVr
------END PRIVATE KEY-----`
-       ssl2, err := ParseCert(cert, key)
-
-       assert.Nil(err)
-       assert.Equal("[\"127.0.0.1\"]", ssl2.Snis)
-
-       // v1 multi domain
-       cert = `-----BEGIN CERTIFICATE-----
-MIICcTCCAdoCCQDQoPEll/bQizANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJD
-TjEOMAwGA1UECAwFbXlrZXkxDjAMBgNVBAcMBW15a2V5MQ4wDAYDVQQKDAVteWtl
-eTEOMAwGA1UECwwFbXlrZXkxDjAMBgNVBAMMBWEuY29tMQ4wDAYDVQQDDAViLmNv
-bTEOMAwGA1UEAwwFYy5jb20wHhcNMjAwNjE3MDk1MDA0WhcNMzAwNjE1MDk1MDA0
-WjB9MQswCQYDVQQGEwJDTjEOMAwGA1UECAwFbXlrZXkxDjAMBgNVBAcMBW15a2V5
-MQ4wDAYDVQQKDAVteWtleTEOMAwGA1UECwwFbXlrZXkxDjAMBgNVBAMMBWEuY29t
-MQ4wDAYDVQQDDAViLmNvbTEOMAwGA1UEAwwFYy5jb20wgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBANHMrKlfFzJbyYuD0YveK2mOOXR9zXi+vC5lW6RaoyKjx5AL
-yIXQWXURGVnxw1+xbmxWN1MXZyAP7eJYFPa0PIJvW0kbyHkJt/TrCyBLVOqpTqvE
-kDAIde9Fx83556sXD43Oq93lyBraXmR+fXuoLxJQQLhALW1tOg1X3VrxKYXNAgMB
-AAEwDQYJKoZIhvcNAQELBQADgYEAwJ7qV0Tj6JXR035ySVSBG1KBF19DVmMYRKdO
-SAU1j437q+ktTcEWSA0CkH6rg53tP4V1h0tzdhCxisivYynngjtEcZfsrwdIrsSg
-cmOBZ+KTRyZ2fLgH4F8Naz5hBrwmR8ZIG46feVOV/swJzz4BNaXGj1oATWkLMA3c
-Sf0G+aI=
------END CERTIFICATE-----`
-       key = `-----BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQDRzKypXxcyW8mLg9GL3itpjjl0fc14vrwuZVukWqMio8eQC8iF
-0Fl1ERlZ8cNfsW5sVjdTF2cgD+3iWBT2tDyCb1tJG8h5Cbf06wsgS1TqqU6rxJAw
-CHXvRcfN+eerFw+Nzqvd5cga2l5kfn17qC8SUEC4QC1tbToNV91a8SmFzQIDAQAB
-AoGBAJIL/y4wqf8+ckES1G6fjG0AuvJjGQQzEuDhYjg5eFMG3EdkTIUKkxuxeYpp
-iG43H/1+zyiipAFn1Vu5oW5T7cJEgC1YA39dERT605S5BrNWWHoZsgH+qmLoq7X+
-jXMlmCagwlgwhUWMU2M1/LUbAl42384dK9u3EwcCgS//sFuBAkEA6mK52/Z03PB3
-0sS14eN7xFl96yc/NcneJ7Vy5APT0KGLo0j2S8gpOVW9EYrrzDzWgQ8FLIeed2Zw
-Z4ATksgRXQJBAOUlh5VJkyMdMiDEeJgK9QKtJkuiLZFAzZiWAUqjvSG2j8tWX/iN
-veI1sXCPyQSKoWPN74+23KWL+nW+mUzkzzECQFf+UIB/+keoD5QVPaNcX+7LGjba
-OSTccIa/3C42MaM1wtK+ZZj1wGRCCAU5/mRiwrUZCnw5PgjdcH2q265TZhECQASY
-JgnGOd8AXNrvVYOm5JazJgtqKwO4iua+SzRV6Bre8C8hgjcXkHESpoYdO+iNZwL7
-RAxbnDzte44UzjoOdGECQGtkrBffiyMaQv6LM/6Fa5TXHb1kPtLGIjFSygR3eTYI
-gHG78R5ac0dzhbyKaOo6cbj7CJVkbBh4BNW94tBZE/I=
------END RSA PRIVATE KEY-----`
-
-       ssl3, err := ParseCert(cert, key)
-
-       assert.Nil(err)
-       assert.Equal("[\"a.com\",\"b.com\",\"c.com\"]", ssl3.Snis)
-}
-
-func TestSslCurd(t *testing.T) {
-       //test3.com
-       param := []byte(`{
-               "cert": "-----BEGIN 
CERTIFICATE-----\nMIIEWjCCAsKgAwIBAgIRAMLLNCKEvgEQL22Hpox6E1kwDQYJKoZIhvcNAQELBQAw\nfzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSowKAYDVQQLDCFqdW54\ndWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikxMTAvBgNVBAMMKG1rY2VydCBq\ndW54dWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikwHhcNMTkwNjAxMDAwMDAw\nWhcNMzAwNjA5MTA0MjA1WjBVMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQg\nY2VydGlmaWNhdGUxKjAoBgNVBAsMIWp1bnh1Y2hlbkBqdW54dWRlQWlyIChqdW54\ndSBjaGVuKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2l
 [...]
-               "key": "-----BEGIN PRIVATE 
KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC9pYPr8x5ESArP\nDx7+lFcVxW6y+sJbHbqziApFuXWilCcs1GUGZddQivUljpPLwHO496UOzM9ea4X0\nAeefFh8yP1122dTa2a06S2i9H1luZ+ISBPBG2H9x8v8TPIEVF7FjBHsatlgv0T30\nwkCGfOb1EgDUu9hOax3W2t2OSDK/G5/zVINbJti8WUJmVerQTqWJ4m8o+218cPJM\na+MPgf+YwwT5sC+fW3aGrRLNRY3R88/n21tSuDXR2WRKLWKpEIQktPSZ8BrMHQK4\nsviLOOJLf4LcO51Vprlf3kGsTxB1ROAcL3Zr9dSLD7I+oYn9t4F41yyB8eugmP0u\nCPz9GpZZAgMBAAECggEAZ2+8SVgb/QASLSdBL3d3HB/IJgSRNyM67qrXd
 [...]
-       }`)
-
-       err := SslCreate(param, u1.String())
-
-       assert := assert.New(t)
-       assert.Nil(err)
-
-       //get item
-       ssl, err := SslItem(u1.String())
-       assert.Nil(err)
-       assert.Equal(uint64(1), ssl.Status)
-       assert.Equal(2, len(ssl.Snis))
-       for _, dm := range ssl.Snis {
-               assert.Equal(true, strings.Contains(dm, "test3.com"))
-       }
-
-       //test3.com duplicate
-       param = []byte(`{
-               "cert": "-----BEGIN 
CERTIFICATE-----\nMIIEWjCCAsKgAwIBAgIRAMLLNCKEvgEQL22Hpox6E1kwDQYJKoZIhvcNAQELBQAw\nfzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSowKAYDVQQLDCFqdW54\ndWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikxMTAvBgNVBAMMKG1rY2VydCBq\ndW54dWNoZW5AanVueHVkZUFpciAoanVueHUgY2hlbikwHhcNMTkwNjAxMDAwMDAw\nWhcNMzAwNjA5MTA0MjA1WjBVMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQg\nY2VydGlmaWNhdGUxKjAoBgNVBAsMIWp1bnh1Y2hlbkBqdW54dWRlQWlyIChqdW54\ndSBjaGVuKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2l
 [...]
-               "key": "-----BEGIN PRIVATE 
KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC9pYPr8x5ESArP\nDx7+lFcVxW6y+sJbHbqziApFuXWilCcs1GUGZddQivUljpPLwHO496UOzM9ea4X0\nAeefFh8yP1122dTa2a06S2i9H1luZ+ISBPBG2H9x8v8TPIEVF7FjBHsatlgv0T30\nwkCGfOb1EgDUu9hOax3W2t2OSDK/G5/zVINbJti8WUJmVerQTqWJ4m8o+218cPJM\na+MPgf+YwwT5sC+fW3aGrRLNRY3R88/n21tSuDXR2WRKLWKpEIQktPSZ8BrMHQK4\nsviLOOJLf4LcO51Vprlf3kGsTxB1ROAcL3Zr9dSLD7I+oYn9t4F41yyB8eugmP0u\nCPz9GpZZAgMBAAECggEAZ2+8SVgb/QASLSdBL3d3HB/IJgSRNyM67qrXd
 [...]
-       }`)
-
-       err = SslCreate(param, u2.String())
-       assert.NotNil(err)
-       assert.Equal(errno.DuplicateSslCert.Code, 
err.(*errno.ManagerError).Code)
-
-       //a.com b.com fail
-       param = []byte(`{
-               "cert": "-----BEGIN 
CERTIFICATE-----\nMIICcTCCAdoCCQDQoPEll/bQizANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJD\nTjEOMAwGA1UECAwFbXlrZXkxDjAMBgNVBAcMBW15a2V5MQ4wDAYDVQQKDAVteWtl\neTEOMAwGA1UECwwFbXlrZXkxDjAMBgNVBAMMBWEuY29tMQ4wDAYDVQQDDAViLmNv\nbTEOMAwGA1UEAwwFYy5jb20wHhcNMjAwNjE3MDk1MDA0WhcNMzAwNjE1MDk1MDA0\nWjB9MQswCQYDVQQGEwJDTjEOMAwGA1UECAwFbXlrZXkxDjAMBgNVBAcMBW15a2V5\nMQ4wDAYDVQQKDAVteWtleTEOMAwGA1UECwwFbXlrZXkxDjAMBgNVBAMMBWEuY29t\nMQ4wDAYDVQQDDAViLmNvbTEOMAwGA1UEAwwFYy5jb20wgZ8wDQYJKoZI
 [...]
-               "key": "-----BEGIN RSA PRIVATE 
KEY-----\nMIICXAIBAAKBgQDRzKypXxcyW8mLg9GL3itpjjl0fc14vrwuZVukWqMio8eQC8iF\n0Fl1ERlZ8cNfsW5sVjdTF2cgD+3iWBT2tDyCb1tJG8h5Cbf06wsgS1TqqU6rxJAw\nCHXvRcfN+eerFw+Nzqvd5cga2l5kfn17qC8SUEC4QC1tbToNV91a8SmFzQIDAQAB\nAoGBAJIL/y4wqf8+ckES1G6fjG0AuvJjGQQzEuDhYjg5eFMG3EdkTIUKkxuxeYpp\niG43H/1+zyiipAFn1Vu5oW5T7cJEgC1YA39dERT605S5BrNWWHoZsgH+qmLoq7X+\njXMlmCagwlgwhUWMU2M1/LUbAl42384dK9u3EwcCgS//sFuBAkEA6mK52/Z03PB3\n0sS14eN7xFl96yc/NcneJ7Vy5APT0KGLo0j2S8gpOVW9EYrrzDzWg
 [...]
-       }`)
-
-       err = SslCreate(param, u1.String())
-       assert.NotNil(err)
-       assert.Equal(errno.DBWriteError.Code, err.(*errno.ManagerError).Code)
-
-       //a.com b.com  ok
-       param = []byte(`{
-               "cert": "-----BEGIN 
CERTIFICATE-----\nMIICcTCCAdoCCQDQoPEll/bQizANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJD\nTjEOMAwGA1UECAwFbXlrZXkxDjAMBgNVBAcMBW15a2V5MQ4wDAYDVQQKDAVteWtl\neTEOMAwGA1UECwwFbXlrZXkxDjAMBgNVBAMMBWEuY29tMQ4wDAYDVQQDDAViLmNv\nbTEOMAwGA1UEAwwFYy5jb20wHhcNMjAwNjE3MDk1MDA0WhcNMzAwNjE1MDk1MDA0\nWjB9MQswCQYDVQQGEwJDTjEOMAwGA1UECAwFbXlrZXkxDjAMBgNVBAcMBW15a2V5\nMQ4wDAYDVQQKDAVteWtleTEOMAwGA1UECwwFbXlrZXkxDjAMBgNVBAMMBWEuY29t\nMQ4wDAYDVQQDDAViLmNvbTEOMAwGA1UEAwwFYy5jb20wgZ8wDQYJKoZI
 [...]
-               "key": "-----BEGIN RSA PRIVATE 
KEY-----\nMIICXAIBAAKBgQDRzKypXxcyW8mLg9GL3itpjjl0fc14vrwuZVukWqMio8eQC8iF\n0Fl1ERlZ8cNfsW5sVjdTF2cgD+3iWBT2tDyCb1tJG8h5Cbf06wsgS1TqqU6rxJAw\nCHXvRcfN+eerFw+Nzqvd5cga2l5kfn17qC8SUEC4QC1tbToNV91a8SmFzQIDAQAB\nAoGBAJIL/y4wqf8+ckES1G6fjG0AuvJjGQQzEuDhYjg5eFMG3EdkTIUKkxuxeYpp\niG43H/1+zyiipAFn1Vu5oW5T7cJEgC1YA39dERT605S5BrNWWHoZsgH+qmLoq7X+\njXMlmCagwlgwhUWMU2M1/LUbAl42384dK9u3EwcCgS//sFuBAkEA6mK52/Z03PB3\n0sS14eN7xFl96yc/NcneJ7Vy5APT0KGLo0j2S8gpOVW9EYrrzDzWg
 [...]
-       }`)
-
-       err = SslCreate(param, u2.String())
-       assert.Nil(err)
-
-       //list
-       count, list, err := SslList(2, 1, -1, 0, 0, "", "asc")
-       assert.Equal(true, count >= 2)
-       assert.Equal(1, len(list))
-
-       // check sni ssl exist
-       param = []byte(`[
-               "test3.com",
-               "www.test3.com",
-               "a.com"
-       ]`)
-
-       err = CheckSniExists(param)
-       assert.Nil(err)
-
-       // check sni ssl exist
-       param = []byte(`[
-               "test3.com",
-               "a.test3.com",
-               "b.com"
-       ]`)
-       err = CheckSniExists(param)
-       assert.NotNil(err)
-
-       // patch
-       param = []byte(`{
-               "status": 0
-       }`)
-       err = SslPatch(param, u1.String())
-       assert.Nil(err)
-
-       ssl, err = SslItem(u1.String())
-       assert.Equal(uint64(0), ssl.Status)
-
-       // check sni ssl exist  --- disable test3
-       param = []byte(`[
-               "test3.com",
-               "www.test3.com",
-               "a.com"
-       ]`)
-
-       err = CheckSniExists(param)
-       assert.NotNil(err)
-
-       param = []byte(`[
-               "a.com"
-       ]`)
-       err = CheckSniExists(param)
-       assert.Nil(err)
-
-       //update
-       param = []byte(`{
-               "cert": "-----BEGIN 
CERTIFICATE-----\nMIIEWzCCAsOgAwIBAgIQDYoN+el2w074sSGlyKVZFTANBgkqhkiG9w0BAQsFADB/\nMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExKjAoBgNVBAsMIWp1bnh1\nY2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTExMC8GA1UEAwwobWtjZXJ0IGp1\nbnh1Y2hlbkBqdW54dWRlQWlyIChqdW54dSBjaGVuKTAeFw0xOTA2MDEwMDAwMDBa\nFw0zMDA3MDQwNjA0MzNaMFUxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBj\nZXJ0aWZpY2F0ZTEqMCgGA1UECwwhanVueHVjaGVuQGp1bnh1ZGVBaXIgKGp1bnh1\nIGNoZW4pMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy21L
 [...]
-               "key": "-----BEGIN PRIVATE 
KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLbUtgWZBileYy\nVSPJvBsnffybAqbFj7BMQksGHDu0Fxq71oWOPI7hpGmHiul0xCAKfiXBMwTaVsV1\nGEfNTn5LL0mwjWT738nyxlJpMiP2lo5fY9icQ6gWMjH3CklGl4s0GPLcgJLccLhL\nNNsNUCT0tkgsu//zW+3UqlDUeg+kT45nXBf4IvT/pGc2Z1qqCua20+/Sy6X3Ih4r\nPX0evbqnHuDpSegrSjytLAKpWaOhVMn55jbOabNKGoU9MsWC81mYx4vd0+aDqcZ2\nOOxuRdLnS2HJMNv+H5gi8Sxl+sNWBtXaDo/8qLJ8oLJ68xDF3Unn9QjgeW0jcxeC\numhqIOJXAgMBAAECggEARdPea9RSm4SY3+4ZusW3DHdSnmLqnCYWfhbDa
 [...]
-       }`)
-
-       err = SslUpdate(param, u1.String())
-       assert.Nil(err)
-
-       ssl, _ = SslItem(u1.String())
-       assert.Equal(2, len(ssl.Snis))
-
-       // check sni ssl exist
-       param = []byte(`[
-               "example.com",
-               "www.example.com",
-               "a.example.com",
-               "a.com",
-               "b.com"
-       ]`)
-
-       err = CheckSniExists(param)
-       assert.NotNil(err)
-       assert.Equal(errno.SslForSniNotExists.Code, 
err.(*errno.ManagerError).Code)
-
-       param = []byte(`{
-               "status": 1
-       }`)
-       err = SslPatch(param, u1.String())
-       assert.Nil(err)
-
-       // check sni ssl exist
-       param = []byte(`[
-               "example.com",
-               "www.example.com",
-               "a.example.com",
-               "a.com",
-               "b.com"
-       ]`)
-
-       err = CheckSniExists(param)
-       assert.Nil(err)
-
-       //delete
-       err = SslDelete(u1.String())
-       assert.Nil(err)
-
-       _, err = SslItem(u1.String())
-       assert.Equal(errno.DBReadError.Code, err.(*errno.ManagerError).Code)
-
-       err = SslDelete(u2.String())
-       assert.Nil(err)
-}
diff --git a/api/service/upstream_test.go b/api/service/upstream_test.go
deleted file mode 100644
index a4d671b..0000000
--- a/api/service/upstream_test.go
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package service
-
-import (
-       "testing"
-
-       uuid "github.com/satori/go.uuid"
-       "github.com/stretchr/testify/assert"
-)
-
-// parse from params to RouteRequest must be error
-func TestUpstreamRequest_Parse(t *testing.T) {
-       a := assert.New(t)
-       param := []byte(`{
-               "name": "upstream-test",
-               "description": "test upstream",
-               "type": "roundrobin",
-               "nodes": {
-                       "127.0.0.1:8080":100,
-                       "127.0.0.1:8081":200
-               },
-               "timeout":{
-                       "connect":15,
-                       "send":15,
-                       "read":15
-               },
-               "enable_websocket": true,
-               "hash_on": "header",
-               "key": "server_addr",
-               "checks": {
-                       "active": {
-                               "timeout": 5,
-                               "http_path": "/status",
-                               "host": "foo.com",
-                               "healthy": {
-                                       "interval": 2,
-                                       "successes": 1
-                               },
-                               "unhealthy": {
-                                       "interval": 1,
-                                       "http_failures": 2
-                               },
-                               "req_headers": ["User-Agent: curl/7.29.0"]
-                       },
-                       "passive": {
-                               "healthy": {
-                                       "http_statuses": [200, 201],
-                                       "successes": 3
-                               },
-                               "unhealthy": {
-                                       "http_statuses": [500],
-                                       "http_failures": 3,
-                                       "tcp_failures": 3
-                               }
-                       }
-               }       
-       }`)
-
-       ur := &UpstreamRequest{}
-       err := ur.Parse(param)
-       a.Nil(err)
-       a.Equal("header", ur.HashOn)
-       a.Equal("server_addr", ur.Key)
-
-       u4 := uuid.NewV4()
-       uuid := u4.String()
-       ur.Id = uuid
-
-       aur, err := ur.Parse2Apisix()
-       a.Nil(err)
-
-       res := aur.toJson()
-       a.NotNil(res)
-
-       //create a upstream
-       apisixResp, err := aur.Create()
-       a.Nil(err)
-       rur, err := apisixResp.Parse2Request()
-       a.Nil(err)
-       a.Equal(ur.Key, rur.Key)
-
-       aur.Id = rur.Id
-       //get the upstream just created
-       created, err := aur.FindById()
-       a.Nil(err)
-       createdFormat, err := created.Parse2Request()
-       a.Nil(err)
-       a.Equal(createdFormat.HashOn, rur.HashOn)
-
-       //delete test data
-       _, err = aur.Delete()
-       a.Nil(err)
-}

Reply via email to