You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by bz...@apache.org on 2022/03/17 06:12:15 UTC
[apisix-dashboard] branch master updated: feat: storage grafana path in to etcd (#2362)
This is an automated email from the ASF dual-hosted git repository.
bzp2010 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new edeed6b feat: storage grafana path in to etcd (#2362)
edeed6b is described below
commit edeed6ba5097f8d715dbc2c400c051bdb7de1dea
Author: LetsGO <97...@qq.com>
AuthorDate: Thu Mar 17 14:12:10 2022 +0800
feat: storage grafana path in to etcd (#2362)
---
api/go.mod | 1 -
api/go.sum | 3 -
api/internal/core/entity/entity.go | 9 +
api/internal/core/store/storehub.go | 13 ++
.../handler/system_config/system_config.go | 132 +++++++++++
.../handler/system_config/system_config_test.go | 258 +++++++++++++++++++++
api/internal/route.go | 4 +-
api/test/e2enew/go.mod | 32 ---
api/test/e2enew/go.sum | 2 -
.../system_config/system_config_suite_test.go | 28 +++
.../e2enew/system_config/system_config_test.go | 126 ++++++++++
11 files changed, 569 insertions(+), 39 deletions(-)
diff --git a/api/go.mod b/api/go.mod
index 257f9b7..691ecfc 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -15,7 +15,6 @@ require (
github.com/evanphx/json-patch/v5 v5.1.0
github.com/getkin/kin-openapi v0.33.0
github.com/gin-contrib/gzip v0.0.3
- github.com/gin-contrib/pprof v1.3.0
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e
github.com/gin-gonic/gin v1.6.3
github.com/golang-jwt/jwt v3.2.2+incompatible
diff --git a/api/go.sum b/api/go.sum
index a3be366..19d50c6 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -120,14 +120,11 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.3 h1:etUaeesHhEORpZMp18zoOhepboiWnFtXrBZxszWUn4k=
github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc=
-github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
-github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e h1:8bZpGwoPxkaivQPrAbWl+7zjjUcbFUnYp7yQcx2r2N0=
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e/go.mod h1:VhW/Ch/3FhimwZb8Oj+qJmdMmoB8r7lmJ5auRjm50oQ=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
-github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
diff --git a/api/internal/core/entity/entity.go b/api/internal/core/entity/entity.go
index f7d4857..4161696 100644
--- a/api/internal/core/entity/entity.go
+++ b/api/internal/core/entity/entity.go
@@ -304,3 +304,12 @@ type StreamRoute struct {
UpstreamID interface{} `json:"upstream_id,omitempty"`
Plugins map[string]interface{} `json:"plugins,omitempty"`
}
+
+// swagger:model SystemConfig
+type SystemConfig struct {
+ ConfigName string `json:"config_name"`
+ Desc string `json:"desc,omitempty"`
+ Payload map[string]interface{} `json:"payload,omitempty"`
+ CreateTime int64 `json:"create_time,omitempty"`
+ UpdateTime int64 `json:"update_time,omitempty"`
+}
diff --git a/api/internal/core/store/storehub.go b/api/internal/core/store/storehub.go
index 1184a3f..76d15fe 100644
--- a/api/internal/core/store/storehub.go
+++ b/api/internal/core/store/storehub.go
@@ -40,6 +40,7 @@ const (
HubKeyPluginConfig HubKey = "plugin_config"
HubKeyProto HubKey = "proto"
HubKeyStreamRoute HubKey = "stream_route"
+ HubKeySystemConfig HubKey = "system_config"
)
var (
@@ -229,5 +230,17 @@ func InitStores() error {
return err
}
+ err = InitStore(HubKeySystemConfig, GenericStoreOption{
+ BasePath: conf.ETCDConfig.Prefix + "/system_config",
+ ObjType: reflect.TypeOf(entity.SystemConfig{}),
+ KeyFunc: func(obj interface{}) string {
+ r := obj.(*entity.SystemConfig)
+ return r.ConfigName
+ },
+ })
+ if err != nil {
+ return err
+ }
+
return nil
}
diff --git a/api/internal/handler/system_config/system_config.go b/api/internal/handler/system_config/system_config.go
new file mode 100644
index 0000000..b74acb3
--- /dev/null
+++ b/api/internal/handler/system_config/system_config.go
@@ -0,0 +1,132 @@
+/*
+ * 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 system_config
+
+import (
+ "errors"
+ "reflect"
+ "time"
+
+ "github.com/gin-gonic/gin"
+ "github.com/shiningrush/droplet"
+ "github.com/shiningrush/droplet/wrapper"
+ wgin "github.com/shiningrush/droplet/wrapper/gin"
+
+ "github.com/apisix/manager-api/internal/core/entity"
+ "github.com/apisix/manager-api/internal/core/store"
+ "github.com/apisix/manager-api/internal/handler"
+)
+
+type Handler struct {
+ systemConfig store.Interface
+}
+
+func NewHandler() (handler.RouteRegister, error) {
+ return &Handler{
+ systemConfig: store.GetStore(store.HubKeySystemConfig),
+ }, nil
+}
+
+func (h *Handler) ApplyRoute(r *gin.Engine) {
+ r.GET("/apisix/admin/system_config/:config_name", wgin.Wraps(h.Get,
+ wrapper.InputType(reflect.TypeOf(GetInput{}))))
+ r.POST("/apisix/admin/system_config", wgin.Wraps(h.Post,
+ wrapper.InputType(reflect.TypeOf(entity.SystemConfig{}))))
+ r.PUT("/apisix/admin/system_config", wgin.Wraps(h.Put,
+ wrapper.InputType(reflect.TypeOf(entity.SystemConfig{}))))
+ r.DELETE("/apisix/admin/system_config/:config_name", wgin.Wraps(h.Delete,
+ wrapper.InputType(reflect.TypeOf(DeleteInput{}))))
+}
+
+type GetInput struct {
+ ConfigName string `auto_read:"config_name,path" validate:"required"`
+}
+
+func (h *Handler) Get(c droplet.Context) (interface{}, error) {
+ input := c.Input().(*GetInput)
+ r, err := h.systemConfig.Get(c.Context(), input.ConfigName)
+
+ if err != nil {
+ return handler.SpecCodeResponse(err), err
+ }
+
+ return r, nil
+}
+
+func (h *Handler) Post(c droplet.Context) (interface{}, error) {
+ input := c.Input().(*entity.SystemConfig)
+ input.CreateTime = time.Now().Unix()
+ input.UpdateTime = time.Now().Unix()
+
+ // TODO use json schema to do it
+ if err := h.checkSystemConfig(input); err != nil {
+ return handler.SpecCodeResponse(err), err
+ }
+
+ // create
+ res, err := h.systemConfig.Create(c.Context(), input)
+ if err != nil {
+ return handler.SpecCodeResponse(err), err
+ }
+
+ return res, nil
+}
+
+func (h *Handler) Put(c droplet.Context) (interface{}, error) {
+ input := c.Input().(*entity.SystemConfig)
+ input.UpdateTime = time.Now().Unix()
+
+ // TODO use json schema to do it
+ if err := h.checkSystemConfig(input); err != nil {
+ return handler.SpecCodeResponse(err), err
+ }
+
+ // update
+ res, err := h.systemConfig.Update(c.Context(), input, false)
+ if err != nil {
+ return handler.SpecCodeResponse(err), err
+ }
+
+ return res, nil
+}
+
+type DeleteInput struct {
+ ConfigName string `auto_read:"config_name,path" validate:"required"`
+}
+
+func (h *Handler) Delete(c droplet.Context) (interface{}, error) {
+ input := c.Input().(*DeleteInput)
+ err := h.systemConfig.BatchDelete(c.Context(), []string{input.ConfigName})
+
+ if err != nil {
+ return handler.SpecCodeResponse(err), err
+ }
+
+ return nil, nil
+}
+
+func (h *Handler) checkSystemConfig(input *entity.SystemConfig) error {
+ if len(input.ConfigName) < 1 || len(input.ConfigName) > 100 {
+ return errors.New("invalid params: config_name length must be between 1 and 100")
+ }
+
+ if len(input.Payload) < 1 {
+ return errors.New("invalid params: payload is required")
+ }
+
+ return nil
+}
diff --git a/api/internal/handler/system_config/system_config_test.go b/api/internal/handler/system_config/system_config_test.go
new file mode 100644
index 0000000..ca5d6ac
--- /dev/null
+++ b/api/internal/handler/system_config/system_config_test.go
@@ -0,0 +1,258 @@
+/*
+ * 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 system_config
+
+import (
+ "errors"
+ "testing"
+
+ "github.com/shiningrush/droplet"
+ "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/store"
+)
+
+func TestSystem_Get(t *testing.T) {
+ t.Parallel()
+ type testCase struct {
+ caseDesc string
+ giveInput *GetInput
+ wantErr error
+ wantRet interface{}
+ mockStore store.Interface
+ mockFunc func(tc *testCase)
+ }
+
+ cases := []*testCase{
+ {
+ caseDesc: "system config not found",
+ giveInput: &GetInput{ConfigName: "grafana"},
+ wantErr: data.ErrNotFound,
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("Get", mock.Anything, mock.Anything).Return(nil, tc.wantErr)
+ tc.mockStore = mockStore
+ },
+ },
+ {
+ caseDesc: "get system config success",
+ giveInput: &GetInput{ConfigName: "grafana"},
+ wantErr: nil,
+ wantRet: entity.SystemConfig{
+ ConfigName: "grafana",
+ Payload: map[string]interface{}{
+ "url": "http://127.0.0.1:3000",
+ },
+ },
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("Get", mock.Anything, mock.Anything).Return(tc.wantRet, nil)
+ tc.mockStore = mockStore
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.caseDesc, func(t *testing.T) {
+ tc.mockFunc(tc)
+ h := Handler{tc.mockStore}
+ ctx := droplet.NewContext()
+ ctx.SetInput(tc.giveInput)
+ ret, err := h.Get(ctx)
+ assert.Equal(t, err, tc.wantErr)
+ if err == nil {
+ assert.Equal(t, ret, tc.wantRet)
+ }
+ })
+ }
+}
+
+func TestSystem_Post(t *testing.T) {
+ t.Parallel()
+ type testCase struct {
+ caseDesc string
+ giveInput *entity.SystemConfig
+ wantErr error
+ wantRet interface{}
+ mockStore store.Interface
+ mockFunc func(tc *testCase)
+ }
+
+ systemConfig := entity.SystemConfig{
+ ConfigName: "grafana",
+ Payload: map[string]interface{}{
+ "url": "http://127.0.0.1:3000",
+ },
+ }
+
+ cases := []*testCase{
+ {
+ caseDesc: "create system config error",
+ giveInput: &systemConfig,
+ wantErr: errors.New("mock error"),
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("Create", mock.Anything, mock.Anything).Return(nil, tc.wantErr)
+ tc.mockStore = mockStore
+ },
+ },
+ {
+ caseDesc: "create system config success",
+ giveInput: &systemConfig,
+ wantErr: nil,
+ wantRet: entity.SystemConfig{
+ ConfigName: "grafana",
+ Payload: map[string]interface{}{
+ "url": "http://127.0.0.1:3000",
+ },
+ },
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("Create", mock.Anything, mock.Anything).Return(tc.wantRet, nil)
+ tc.mockStore = mockStore
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.caseDesc, func(t *testing.T) {
+ tc.mockFunc(tc)
+ h := Handler{tc.mockStore}
+ ctx := droplet.NewContext()
+ ctx.SetInput(tc.giveInput)
+ ret, err := h.Post(ctx)
+ assert.Equal(t, err, tc.wantErr)
+ if err == nil {
+ assert.Equal(t, ret, tc.wantRet)
+ }
+ })
+ }
+}
+
+func TestSystem_Put(t *testing.T) {
+ t.Parallel()
+ type testCase struct {
+ caseDesc string
+ giveInput *entity.SystemConfig
+ wantErr error
+ wantRet interface{}
+ mockStore store.Interface
+ mockFunc func(tc *testCase)
+ }
+
+ systemConfig := entity.SystemConfig{
+ ConfigName: "grafana",
+ Payload: map[string]interface{}{
+ "url": "http://127.0.0.1:3000",
+ },
+ }
+
+ cases := []*testCase{
+ {
+ caseDesc: "update system config error",
+ giveInput: &systemConfig,
+ wantErr: errors.New("mock error"),
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(nil, tc.wantErr)
+ tc.mockStore = mockStore
+ },
+ },
+ {
+ caseDesc: "update system config success",
+ giveInput: &systemConfig,
+ wantErr: nil,
+ wantRet: entity.SystemConfig{
+ ConfigName: "grafana",
+ Payload: map[string]interface{}{
+ "url": "http://127.0.0.1:3000",
+ },
+ },
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(tc.wantRet, nil)
+ tc.mockStore = mockStore
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.caseDesc, func(t *testing.T) {
+ tc.mockFunc(tc)
+ h := Handler{tc.mockStore}
+ ctx := droplet.NewContext()
+ ctx.SetInput(tc.giveInput)
+ ret, err := h.Put(ctx)
+ assert.Equal(t, err, tc.wantErr)
+ if err == nil {
+ assert.Equal(t, ret, tc.wantRet)
+ }
+ })
+ }
+}
+
+func TestSystem_Delete(t *testing.T) {
+ t.Parallel()
+ type testCase struct {
+ caseDesc string
+ giveInput *DeleteInput
+ wantErr error
+ wantRet interface{}
+ mockStore store.Interface
+ mockFunc func(tc *testCase)
+ }
+
+ cases := []*testCase{
+ {
+ caseDesc: "delete system config error",
+ giveInput: &DeleteInput{ConfigName: "grafana"},
+ wantErr: errors.New("mock error"),
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("BatchDelete", mock.Anything, mock.Anything).Return(tc.wantErr)
+ tc.mockStore = mockStore
+ },
+ },
+ {
+ caseDesc: "delete system config success",
+ giveInput: &DeleteInput{ConfigName: "grafana"},
+ wantErr: nil,
+ mockFunc: func(tc *testCase) {
+ mockStore := &store.MockInterface{}
+ mockStore.On("BatchDelete", mock.Anything, mock.Anything).Return(tc.wantRet)
+ tc.mockStore = mockStore
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.caseDesc, func(t *testing.T) {
+ tc.mockFunc(tc)
+ h := Handler{tc.mockStore}
+ ctx := droplet.NewContext()
+ ctx.SetInput(tc.giveInput)
+ ret, err := h.Delete(ctx)
+ assert.Equal(t, err, tc.wantErr)
+ if err == nil {
+ assert.Equal(t, ret, tc.wantRet)
+ }
+ })
+ }
+}
diff --git a/api/internal/route.go b/api/internal/route.go
index 5ece4e3..7eddc9c 100644
--- a/api/internal/route.go
+++ b/api/internal/route.go
@@ -21,6 +21,7 @@ import (
"path/filepath"
// "github.com/gin-contrib/pprof"
+ "github.com/gin-contrib/gzip"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
@@ -42,10 +43,10 @@ import (
"github.com/apisix/manager-api/internal/handler/service"
"github.com/apisix/manager-api/internal/handler/ssl"
"github.com/apisix/manager-api/internal/handler/stream_route"
+ "github.com/apisix/manager-api/internal/handler/system_config"
"github.com/apisix/manager-api/internal/handler/tool"
"github.com/apisix/manager-api/internal/handler/upstream"
"github.com/apisix/manager-api/internal/log"
- "github.com/gin-contrib/gzip"
)
func SetUpRouter() *gin.Engine {
@@ -83,6 +84,7 @@ func SetUpRouter() *gin.Engine {
migrate.NewHandler,
proto.NewHandler,
stream_route.NewHandler,
+ system_config.NewHandler,
}
for i := range factories {
diff --git a/api/test/e2enew/go.mod b/api/test/e2enew/go.mod
index 94fdd65..0d6c7fb 100644
--- a/api/test/e2enew/go.mod
+++ b/api/test/e2enew/go.mod
@@ -9,35 +9,3 @@ require (
github.com/stretchr/testify v1.7.0
github.com/tidwall/gjson v1.11.0
)
-
-require (
- github.com/ajg/form v1.5.1 // indirect
- github.com/andybalholm/brotli v1.0.2 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/fatih/structs v1.0.0 // indirect
- github.com/fsnotify/fsnotify v1.4.9 // indirect
- github.com/google/go-querystring v1.0.0 // indirect
- github.com/gorilla/websocket v1.4.2 // indirect
- github.com/imkira/go-interpol v1.0.0 // indirect
- github.com/klauspost/compress v1.12.2 // indirect
- github.com/nxadm/tail v1.4.8 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/sergi/go-diff v1.0.0 // indirect
- github.com/tidwall/match v1.1.1 // indirect
- github.com/tidwall/pretty v1.2.0 // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasthttp v1.27.0 // indirect
- github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
- github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
- github.com/xeipuuv/gojsonschema v1.1.0 // indirect
- github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
- github.com/yudai/gojsondiff v1.0.0 // indirect
- github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
- golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
- golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect
- golang.org/x/text v0.3.6 // indirect
- gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
- gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
- moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e // indirect
-)
diff --git a/api/test/e2enew/go.sum b/api/test/e2enew/go.sum
index b0dbf1b..b6d85c7 100644
--- a/api/test/e2enew/go.sum
+++ b/api/test/e2enew/go.sum
@@ -14,7 +14,6 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gavv/httpexpect/v2 v2.3.1 h1:sGLlKMn8AuHS9ztK9Sb7AJ7OxIL8v2PcLdyxfKt1Fo4=
github.com/gavv/httpexpect/v2 v2.3.1/go.mod h1:yOE8m/aqFYQDNrgprMeXgq4YynfN9h1NgcE1+1suV64=
-github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@@ -137,7 +136,6 @@ golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/api/test/e2enew/system_config/system_config_suite_test.go b/api/test/e2enew/system_config/system_config_suite_test.go
new file mode 100644
index 0000000..122ca1f
--- /dev/null
+++ b/api/test/e2enew/system_config/system_config_suite_test.go
@@ -0,0 +1,28 @@
+/*
+ * 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 system_config
+
+import (
+ "github.com/onsi/ginkgo"
+ "github.com/onsi/gomega"
+ "testing"
+)
+
+func TestSystemConfig(t *testing.T) {
+ gomega.RegisterFailHandler(ginkgo.Fail)
+ ginkgo.RunSpecs(t, "system config suite")
+}
diff --git a/api/test/e2enew/system_config/system_config_test.go b/api/test/e2enew/system_config/system_config_test.go
new file mode 100644
index 0000000..7fc2166
--- /dev/null
+++ b/api/test/e2enew/system_config/system_config_test.go
@@ -0,0 +1,126 @@
+/*
+ * 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 system_config
+
+import (
+ "net/http"
+
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/ginkgo/extensions/table"
+
+ "github.com/apisix/manager-api/test/e2enew/base"
+)
+
+var _ = Describe("system config", func() {
+ DescribeTable("test system config data CURD",
+ func(tc base.HttpTestCase) {
+ base.RunTestCase(tc)
+ },
+
+ Entry("get system config should get not found error", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/system_config/grafana",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusNotFound,
+ }),
+
+ Entry("create system config should get schema validate failed error", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/system_config",
+ Body: `{
+ "config_name": "",
+ "payload": {"url":"http://127.0.0.1:3000"}
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusBadRequest,
+ }),
+
+ Entry("create system config should success", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPost,
+ Path: "/apisix/admin/system_config",
+ Body: `{
+ "config_name": "grafana",
+ "payload": {"url":"http://127.0.0.1:3000"}
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ ExpectBody: "\"config_name\":\"grafana\",\"payload\":{\"url\":\"http://127.0.0.1:3000\"}",
+ }),
+
+ Entry("after create system config get config should succeed", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/system_config/grafana",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ ExpectBody: "\"config_name\":\"grafana\",\"payload\":{\"url\":\"http://127.0.0.1:3000\"}",
+ }),
+
+ Entry("update system config should get schema validate failed error", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/system_config",
+ Body: `{
+ "config_name": "",
+ "payload": {"url":"http://127.0.0.1:2000"}
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusBadRequest,
+ }),
+
+ Entry("update system config should success", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodPut,
+ Path: "/apisix/admin/system_config",
+ Body: `{
+ "config_name": "grafana",
+ "payload": {"url":"http://127.0.0.1:2000"}
+ }`,
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ ExpectBody: "\"config_name\":\"grafana\",\"payload\":{\"url\":\"http://127.0.0.1:2000\"}",
+ }),
+
+ Entry("after update system config get config should succeed", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/system_config/grafana",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ ExpectBody: "\"config_name\":\"grafana\",\"payload\":{\"url\":\"http://127.0.0.1:2000\"}",
+ }),
+
+ Entry("delete system config should success", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodDelete,
+ Path: "/apisix/admin/system_config/grafana",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusOK,
+ }),
+
+ Entry("get system config should get not found error", base.HttpTestCase{
+ Object: base.ManagerApiExpect(),
+ Method: http.MethodGet,
+ Path: "/apisix/admin/system_config/grafana",
+ Headers: map[string]string{"Authorization": base.GetToken()},
+ ExpectStatus: http.StatusNotFound,
+ }),
+ )
+})