This is an automated email from the ASF dual-hosted git repository. chenjunxu 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 5d9cd3f change: remove ID of consumer (#1745)
5d9cd3f is described below
commit 5d9cd3fca2ecca51ff62b1e3623ae3159673b2bc
Author: nic-chen <[email protected]>
AuthorDate: Mon Apr 19 11:21:25 2021 +0800
change: remove ID of consumer (#1745)
---
.github/workflows/backend-e2e-test.yml | 1 +
api/conf/schema.json | 242 +++++++++++----------
api/internal/core/entity/entity.go | 11 +-
api/internal/core/store/store_mock.go | 10 +
api/internal/core/store/validate_test.go | 43 +---
api/internal/handler/consumer/consumer.go | 31 ++-
api/internal/handler/consumer/consumer_test.go | 46 ++--
api/internal/handler/label/label_test.go | 4 -
api/test/docker/apisix_config.yaml | 2 +-
api/test/docker/apisix_config2.yaml | 2 +-
api/test/docker/docker-compose.yaml | 4 +-
api/test/e2enew/schema/schema_test.go | 2 +-
web/cypress/fixtures/plugin-dataset.json | 4 +-
.../create-upstream-with-cors-form.spec.js | 10 +-
web/src/components/Plugin/PluginDetail.tsx | 4 +-
15 files changed, 213 insertions(+), 203 deletions(-)
diff --git a/.github/workflows/backend-e2e-test.yml
b/.github/workflows/backend-e2e-test.yml
index 6f226ad..2914e9b 100644
--- a/.github/workflows/backend-e2e-test.yml
+++ b/.github/workflows/backend-e2e-test.yml
@@ -46,6 +46,7 @@ jobs:
docker-compose up -d
sleep 5
docker logs docker_managerapi_1
+ docker logs docker_apisix_1
- name: run test
working-directory: ./api/test/e2e
diff --git a/api/conf/schema.json b/api/conf/schema.json
index e69c57a..ff58ff4 100644
--- a/api/conf/schema.json
+++ b/api/conf/schema.json
@@ -10,17 +10,6 @@
"maxLength": 256,
"type": "string"
},
- "id": {
- "anyOf": [{
- "maxLength": 64,
- "minLength": 1,
- "pattern": "^[a-zA-Z0-9-_.]+$",
- "type": "string"
- }, {
- "minimum": 1,
- "type": "integer"
- }]
- },
"labels": {
"description": "key/value pairs to
specify attributes",
"maxProperties": 16,
@@ -147,6 +136,27 @@
"maxLength": 1048576,
"minLength": 1,
"type": "string"
+ },
+ "create_time": {
+ "type": "integer"
+ },
+ "desc": {
+ "maxLength": 256,
+ "type": "string"
+ },
+ "id": {
+ "anyOf": [{
+ "maxLength": 64,
+ "minLength": 1,
+ "pattern": "^[a-zA-Z0-9-_.]+$",
+ "type": "string"
+ }, {
+ "minimum": 1,
+ "type": "integer"
+ }]
+ },
+ "update_time": {
+ "type": "integer"
}
},
"required": ["content"],
@@ -595,10 +605,6 @@
"description":
"discovery type",
"type": "string"
},
- "enable_websocket": {
- "description": "enable
websocket for request",
- "type": "boolean"
- },
"hash_on": {
"default": "vars",
"enum": ["consumer",
"cookie", "header", "vars", "vars_combinations"],
@@ -664,6 +670,11 @@
"minimum": 1,
"type": "integer"
},
+
"priority": {
+
"default": 0,
+
"description": "priority of node",
+
"type": "integer"
+
},
"weight": {
"description": "weight of node",
"minimum": 0,
@@ -754,12 +765,6 @@
"uniqueItems": true
},
"vars": {
- "items": {
- "description": "Nginx builtin
variable name and value",
- "maxItems": 4,
- "minItems": 2,
- "type": "array"
- },
"type": "array"
}
},
@@ -1025,10 +1030,6 @@
"description":
"discovery type",
"type": "string"
},
- "enable_websocket": {
- "description": "enable
websocket for request",
- "type": "boolean"
- },
"hash_on": {
"default": "vars",
"enum": ["consumer",
"cookie", "header", "vars", "vars_combinations"],
@@ -1094,6 +1095,11 @@
"minimum": 1,
"type": "integer"
},
+
"priority": {
+
"default": 0,
+
"description": "priority of node",
+
"type": "integer"
+
},
"weight": {
"description": "weight of node",
"minimum": 0,
@@ -1270,6 +1276,13 @@
},
"stream_route": {
"properties": {
+ "create_time": {
+ "type": "integer"
+ },
+ "desc": {
+ "maxLength": 256,
+ "type": "string"
+ },
"id": {
"anyOf": [{
"maxLength": 64,
@@ -1330,6 +1343,9 @@
"description": "server port",
"type": "integer"
},
+ "update_time": {
+ "type": "integer"
+ },
"upstream": {
"additionalProperties": false,
"oneOf": [{
@@ -1535,10 +1551,6 @@
"description":
"discovery type",
"type": "string"
},
- "enable_websocket": {
- "description": "enable
websocket for request",
- "type": "boolean"
- },
"hash_on": {
"default": "vars",
"enum": ["consumer",
"cookie", "header", "vars", "vars_combinations"],
@@ -1604,6 +1616,11 @@
"minimum": 1,
"type": "integer"
},
+
"priority": {
+
"default": 0,
+
"description": "priority of node",
+
"type": "integer"
+
},
"weight": {
"description": "weight of node",
"minimum": 0,
@@ -1887,10 +1904,6 @@
"description": "discovery type",
"type": "string"
},
- "enable_websocket": {
- "description": "enable websocket for
request",
- "type": "boolean"
- },
"hash_on": {
"default": "vars",
"enum": ["consumer", "cookie",
"header", "vars", "vars_combinations"],
@@ -1956,6 +1969,11 @@
"minimum": 1,
"type":
"integer"
},
+ "priority": {
+
"default": 0,
+
"description": "priority of node",
+ "type":
"integer"
+ },
"weight": {
"description": "weight of node",
"minimum": 0,
@@ -2297,54 +2315,59 @@
"priority": 2400,
"schema": {
"$comment": "this is a mark for our injected
plugin schema",
- "oneOf": [{
- "properties": {
- "blacklist": {
- "items": {
- "type": "string"
+ "anyOf": [{
+ "required": ["blacklist"]
+ }, {
+ "required": ["whitelist"]
+ }, {
+ "required": ["allowed_by_methods"]
+ }],
+ "properties": {
+ "allowed_by_methods": {
+ "items": {
+ "properties": {
+ "methods": {
+
"items": {
+
"enum": ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT",
"TRACE"],
+
"type": "string"
+ },
+
"minItems": 1,
+ "type":
"array"
+ },
+ "user": {
+ "type":
"string"
+ }
},
- "minItems": 1,
- "type": "array"
- },
- "rejected_code": {
- "default": 403,
- "minimum": 200,
- "type": "integer"
+ "type": "object"
},
- "type": {
- "default":
"consumer_name",
- "enum":
["consumer_name", "service_id"],
- "type": "string"
- }
+ "type": "array"
},
- "required": ["blacklist"],
- "title": "blacklist"
- }, {
- "properties": {
- "rejected_code": {
- "default": 403,
- "minimum": 200,
- "type": "integer"
- },
- "type": {
- "default":
"consumer_name",
- "enum":
["consumer_name", "service_id"],
+ "blacklist": {
+ "items": {
"type": "string"
},
- "whitelist": {
- "items": {
- "type": "string"
- },
- "minItems": 1,
- "type": "array"
- }
+ "minItems": 1,
+ "type": "array"
},
- "required": ["whitelist"],
- "title": "whitelist"
- }],
- "properties": {
"disable": {
"type": "boolean"
+ },
+ "rejected_code": {
+ "default": 403,
+ "minimum": 200,
+ "type": "integer"
+ },
+ "type": {
+ "default": "consumer_name",
+ "enum": ["consumer_name",
"service_id"],
+ "type": "string"
+ },
+ "whitelist": {
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1,
+ "type": "array"
}
},
"type": "object"
@@ -2376,6 +2399,17 @@
"description": "you can use '*'
to allow all origins when no credentials,'**' to allow forcefully(it will bring
some security risks, be carefully),multiple origin use ',' to split. default:
*.",
"type": "string"
},
+ "allow_origins_by_regex": {
+ "description": "you can use
regex to allow specific origins when no credentials,for example use
[.*\\.test.com] to allow a.test.com and b.test.com",
+ "items": {
+ "maxLength": 4096,
+ "minLength": 1,
+ "type": "string"
+ },
+ "minItems": 1,
+ "type": "array",
+ "uniqueItems": true
+ },
"disable": {
"type": "boolean"
},
@@ -2608,6 +2642,9 @@
"type":
"integer"
},
"vars": {
+ "items": {
+ "type":
"array"
+ },
"maxItems": 20,
"type": "array"
}
@@ -2627,6 +2664,9 @@
"type":
"integer"
},
"vars": {
+ "items": {
+ "type":
"array"
+ },
"maxItems": 20,
"type": "array"
}
@@ -3682,6 +3722,9 @@
"maximum": 598,
"minimum": 200,
"type": "integer"
+ },
+ "vars": {
+ "type": "array"
}
},
"type": "object"
@@ -3762,6 +3805,9 @@
"default":
"http://127.0.0.1:12800",
"type": "string"
},
+ "report_interval": {
+ "type": "integer"
+ },
"service_instance_name": {
"default": "APISIX Instance
Name",
"description": "User Service
Instance Name",
@@ -4028,43 +4074,6 @@
"items": {
"properties": {
"vars": {
-
"items": {
-
"additionalItems": {
-
"anyOf": [{
-
"type": "string"
-
}, {
-
"type": "number"
-
}, {
-
"type": "boolean"
-
}, {
-
"items": {
-
"anyOf": [{
-
"maxLength": 100,
-
"minLength": 1,
-
"type": "string"
-
}, {
-
"type": "number"
-
}, {
-
"type": "boolean"
-
}]
-
},
-
"type": "array",
-
"uniqueItems": true
-
}]
-
},
-
"items": [{
-
"maxLength": 100,
-
"minLength": 1,
-
"type": "string"
-
}, {
-
"maxLength": 2,
-
"minLength": 1,
-
"type": "string"
-
}],
-
"maxItems": 10,
-
"minItems": 0,
-
"type": "array"
-
},
"type": "array"
}
},
@@ -4283,10 +4292,6 @@
"description": "discovery type",
"type": "string"
},
-
"enable_websocket": {
-
"description": "enable websocket for request",
-
"type": "boolean"
-
},
"hash_on": {
"default": "vars",
"enum": ["consumer", "cookie", "header",
"vars", "vars_combinations"],
@@ -4352,6 +4357,11 @@
"minimum": 1,
"type":
"integer"
},
+
"priority": {
+
"default": 0,
+
"description":
"priority of node",
+
"type":
"integer"
+
},
"weight": {
"description":
"weight of node",
"minimum": 0,
@@ -4578,6 +4588,10 @@
"default": "APISIX",
"description": "service name
for zipkin reporter",
"type": "string"
+ },
+ "span_version": {
+ "default": 2,
+ "enum": [1, 2]
}
},
"required": ["endpoint", "sample_ratio"],
diff --git a/api/internal/core/entity/entity.go
b/api/internal/core/entity/entity.go
index c42d31f..b81c7f4 100644
--- a/api/internal/core/entity/entity.go
+++ b/api/internal/core/entity/entity.go
@@ -197,11 +197,12 @@ func (upstream *Upstream) Parse2NameResponse()
(*UpstreamNameResponse, error) {
// swagger:model Consumer
type Consumer struct {
- BaseInfo
- Username string `json:"username"`
- Desc string `json:"desc,omitempty"`
- Plugins map[string]interface{} `json:"plugins,omitempty"`
- Labels map[string]string `json:"labels,omitempty"`
+ Username string `json:"username"`
+ Desc string `json:"desc,omitempty"`
+ Plugins map[string]interface{} `json:"plugins,omitempty"`
+ Labels map[string]string `json:"labels,omitempty"`
+ CreateTime int64 `json:"create_time,omitempty"`
+ UpdateTime int64 `json:"update_time,omitempty"`
}
// swagger:model SSL
diff --git a/api/internal/core/store/store_mock.go
b/api/internal/core/store/store_mock.go
index 436ef6b..c6801d6 100644
--- a/api/internal/core/store/store_mock.go
+++ b/api/internal/core/store/store_mock.go
@@ -18,6 +18,7 @@ package store
import (
"context"
+ "sort"
"github.com/stretchr/testify/mock"
)
@@ -44,6 +45,15 @@ func (m *MockInterface) List(_ context.Context, input
ListInput) (*ListOutput, e
} else {
r0 = ret.Get(0).(*ListOutput)
}
+
+ if input.Less == nil {
+ input.Less = defLessFunc
+ }
+
+ sort.Slice(r0.Rows, func(i, j int) bool {
+ return input.Less(r0.Rows[i], r0.Rows[j])
+ })
+
r1 = ret.Error(1)
return r0, r1
diff --git a/api/internal/core/store/validate_test.go
b/api/internal/core/store/validate_test.go
index 795fab3..7b0b6f3 100644
--- a/api/internal/core/store/validate_test.go
+++ b/api/internal/core/store/validate_test.go
@@ -76,7 +76,6 @@ func TestAPISIXJsonSchemaValidator_Validate(t *testing.T) {
consumer := &entity.Consumer{}
reqBody := `{
- "id": "jack",
"username": "jack",
"plugins": {
"limit-count": {
@@ -93,26 +92,6 @@ func TestAPISIXJsonSchemaValidator_Validate(t *testing.T) {
err = validator.Validate(consumer)
assert.Nil(t, err)
- consumer2 := &entity.Consumer{}
- reqBody = `{
- "username": "jack",
- "plugins": {
- "limit-count": {
- "count": 2,
- "time_window": 60,
- "rejected_code": 503,
- "key": "remote_addr"
- }
- },
- "desc": "test description"
- }`
- err = json.Unmarshal([]byte(reqBody), consumer2)
- assert.Nil(t, err)
-
- err = validator.Validate(consumer2)
- assert.NotNil(t, err)
- assert.EqualError(t, err, "schema validate failed: id: Must validate at
least one schema (anyOf)\nid: Invalid type. Expected: string, given: null")
-
//check nil obj
err = validator.Validate(nil)
assert.NotNil(t, err)
@@ -121,17 +100,16 @@ func TestAPISIXJsonSchemaValidator_Validate(t *testing.T)
{
//plugin schema fail
consumer3 := &entity.Consumer{}
reqBody = `{
- "id": "jack",
- "username": "jack",
- "plugins": {
- "limit-count": {
- "time_window": 60,
- "rejected_code": 503,
- "key": "remote_addr"
- }
- },
- "desc": "test description"
- }`
+ "username": "jack",
+ "plugins": {
+ "limit-count": {
+ "time_window": 60,
+ "rejected_code": 503,
+ "key": "remote_addr"
+ }
+ },
+ "desc": "test description"
+ }`
err = json.Unmarshal([]byte(reqBody), consumer3)
assert.Nil(t, err)
err = validator.Validate(consumer3)
@@ -456,7 +434,6 @@ func TestAPISIXSchemaValidator_Validate(t *testing.T) {
// normal config, should pass
reqBody := `{
- "id": "jack",
"username": "jack",
"plugins": {
"limit-count": {
diff --git a/api/internal/handler/consumer/consumer.go
b/api/internal/handler/consumer/consumer.go
index 7efb238..0b169bb 100644
--- a/api/internal/handler/consumer/consumer.go
+++ b/api/internal/handler/consumer/consumer.go
@@ -17,21 +17,18 @@
package consumer
import (
- "net/http"
"reflect"
"strings"
+ "time"
"github.com/gin-gonic/gin"
"github.com/shiningrush/droplet"
- "github.com/shiningrush/droplet/data"
"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"
- "github.com/apisix/manager-api/internal/utils"
- "github.com/apisix/manager-api/internal/utils/consts"
)
type Handler struct {
@@ -120,6 +117,17 @@ func (h *Handler) List(c droplet.Context) (interface{},
error) {
}
return true
},
+ Less: func(i, j interface{}) bool {
+ iBase := i.(*entity.Consumer)
+ jBase := j.(*entity.Consumer)
+ if iBase.CreateTime != jBase.CreateTime {
+ return iBase.CreateTime < jBase.CreateTime
+ }
+ if iBase.UpdateTime != jBase.UpdateTime {
+ return iBase.UpdateTime < jBase.UpdateTime
+ }
+ return iBase.Username < jBase.Username
+ },
PageSize: input.PageSize,
PageNumber: input.PageNumber,
})
@@ -137,16 +145,21 @@ type SetInput struct {
func (h *Handler) Set(c droplet.Context) (interface{}, error) {
input := c.Input().(*SetInput)
- if input.ID != nil && utils.InterfaceToString(input.ID) !=
input.Username {
- return &data.SpecCodeResponse{StatusCode:
http.StatusBadRequest},
- consts.ErrIDUsername
- }
if input.Username != "" {
input.Consumer.Username = input.Username
}
- input.Consumer.ID = input.Consumer.Username
ensurePluginsDefValue(input.Plugins)
+ // Because the ID of consumer has been removed,
+ // `BaseInfo` is no longer embedded in consumer's struct,
+ // So we need to maintain create_time and update_time separately for
consumer
+ savedConsumer, _ := h.consumerStore.Get(c.Context(),
input.Consumer.Username)
+ input.Consumer.CreateTime = time.Now().Unix()
+ input.Consumer.UpdateTime = time.Now().Unix()
+ if savedConsumer != nil {
+ input.Consumer.CreateTime =
savedConsumer.(*entity.Consumer).CreateTime
+ }
+
ret, err := h.consumerStore.Update(c.Context(), &input.Consumer, true)
if err != nil {
return handler.SpecCodeResponse(err), err
diff --git a/api/internal/handler/consumer/consumer_test.go
b/api/internal/handler/consumer/consumer_test.go
index 0bc5eab..9a76bc9 100644
--- a/api/internal/handler/consumer/consumer_test.go
+++ b/api/internal/handler/consumer/consumer_test.go
@@ -112,8 +112,8 @@ func TestHandler_List(t *testing.T) {
},
wantRet: &store.ListOutput{
Rows: []interface{}{
- &entity.Consumer{Username: "testUser"},
&entity.Consumer{Username:
"iam-testUser"},
+ &entity.Consumer{Username: "testUser"},
&entity.Consumer{Username:
"testUser-is-me"},
},
TotalSize: 3,
@@ -195,9 +195,6 @@ func TestHandler_Create(t *testing.T) {
},
giveCtx: context.WithValue(context.Background(),
"test", "value"),
giveRet: &entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth": map[string]interface{}{
@@ -207,9 +204,6 @@ func TestHandler_Create(t *testing.T) {
},
wantInput: &SetInput{
Consumer: entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth":
map[string]interface{}{
@@ -219,9 +213,6 @@ func TestHandler_Create(t *testing.T) {
},
},
wantRet: &entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth": map[string]interface{}{
@@ -249,9 +240,6 @@ func TestHandler_Create(t *testing.T) {
giveErr: fmt.Errorf("create failed"),
wantInput: &SetInput{
Consumer: entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth":
map[string]interface{}{
@@ -275,10 +263,12 @@ func TestHandler_Create(t *testing.T) {
mStore.On("Update", mock.Anything, mock.Anything,
mock.Anything).Run(func(args mock.Arguments) {
methodCalled = true
assert.Equal(t, tc.giveCtx, args.Get(0))
- assert.Equal(t, &tc.wantInput.Consumer,
args.Get(1))
assert.True(t, args.Bool(2))
}).Return(tc.giveRet, tc.giveErr)
+ mStore.On("Get", mock.Anything).Run(func(args
mock.Arguments) {
+ }).Return(nil, nil)
+
h := Handler{consumerStore: mStore}
ctx := droplet.NewContext()
ctx.SetInput(tc.giveInput)
@@ -302,6 +292,7 @@ func TestHandler_Update(t *testing.T) {
wantInput *entity.Consumer
wantRet interface{}
wantCalled bool
+ getRet interface{}
}{
{
caseDesc: "normal",
@@ -317,20 +308,15 @@ func TestHandler_Update(t *testing.T) {
},
giveCtx: context.WithValue(context.Background(),
"test", "value"),
giveRet: &entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth": map[string]interface{}{
"exp": 500,
},
},
+ CreateTime: 1618648423,
},
wantInput: &entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth": map[string]interface{}{
@@ -339,17 +325,20 @@ func TestHandler_Update(t *testing.T) {
},
},
wantRet: &entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth": map[string]interface{}{
"exp": 500,
},
},
+ CreateTime: 1618648423,
},
wantCalled: true,
+ getRet: &entity.Consumer{
+ Username: "name",
+ CreateTime: 1618648423,
+ UpdateTime: 1618648423,
+ },
},
{
caseDesc: "store update failed",
@@ -366,9 +355,6 @@ func TestHandler_Update(t *testing.T) {
},
giveErr: fmt.Errorf("create failed"),
wantInput: &entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: "name",
- },
Username: "name",
Plugins: map[string]interface{}{
"jwt-auth": map[string]interface{}{
@@ -391,10 +377,12 @@ func TestHandler_Update(t *testing.T) {
mStore.On("Update", mock.Anything, mock.Anything,
mock.Anything).Run(func(args mock.Arguments) {
methodCalled = true
assert.Equal(t, tc.giveCtx, args.Get(0))
- assert.Equal(t, tc.wantInput, args.Get(1))
assert.True(t, args.Bool(2))
}).Return(tc.giveRet, tc.giveErr)
+ mStore.On("Get", mock.Anything).Run(func(args
mock.Arguments) {
+ }).Return(tc.getRet, nil)
+
h := Handler{consumerStore: mStore}
ctx := droplet.NewContext()
ctx.SetInput(tc.giveInput)
@@ -403,6 +391,10 @@ func TestHandler_Update(t *testing.T) {
assert.Equal(t, tc.wantCalled, methodCalled)
assert.Equal(t, tc.wantRet, ret)
assert.Equal(t, tc.wantErr, err)
+ if err == nil {
+ assert.Equal(t,
tc.getRet.(*entity.Consumer).CreateTime, ret.(*entity.Consumer).CreateTime)
+ assert.NotEqual(t,
tc.getRet.(*entity.Consumer).UpdateTime, ret.(*entity.Consumer).UpdateTime)
+ }
})
}
}
diff --git a/api/internal/handler/label/label_test.go
b/api/internal/handler/label/label_test.go
index 664288d..d227b95 100644
--- a/api/internal/handler/label/label_test.go
+++ b/api/internal/handler/label/label_test.go
@@ -167,10 +167,6 @@ func genUpstream(labels map[string]string)
*entity.Upstream {
func genConsumer(labels map[string]string) *entity.Consumer {
r := entity.Consumer{
- BaseInfo: entity.BaseInfo{
- ID: rand.Int(),
- CreateTime: rand.Int63(),
- },
Username: "test",
Labels: labels,
}
diff --git a/api/test/docker/apisix_config.yaml
b/api/test/docker/apisix_config.yaml
index 00fc878..e56a74d 100644
--- a/api/test/docker/apisix_config.yaml
+++ b/api/test/docker/apisix_config.yaml
@@ -22,7 +22,7 @@ etcd:
- "http://172.16.238.10:2379"
- "http://172.16.238.11:2379"
- "http://172.16.238.12:2379"
- resync_delay: 0.1 # sync data from etcd quickly for e2e test
+ resync_delay: 0 # sync data from etcd quickly for e2e test
apisix:
id: "apisix-server1"
diff --git a/api/test/docker/apisix_config2.yaml
b/api/test/docker/apisix_config2.yaml
index bd78898..5d23725 100644
--- a/api/test/docker/apisix_config2.yaml
+++ b/api/test/docker/apisix_config2.yaml
@@ -22,7 +22,7 @@ etcd:
- "http://172.16.238.10:2379"
- "http://172.16.238.11:2379"
- "http://172.16.238.12:2379"
- resync_delay: 0.1 # sync data from etcd quickly for e2e test
+ resync_delay: 0 # sync data from etcd quickly for e2e test
apisix:
id: "apisix-server2"
diff --git a/api/test/docker/docker-compose.yaml
b/api/test/docker/docker-compose.yaml
index 16d6e62..2da0990 100644
--- a/api/test/docker/docker-compose.yaml
+++ b/api/test/docker/docker-compose.yaml
@@ -127,7 +127,7 @@ services:
apisix:
hostname: apisix_server1
- image: apache/apisix:2.4-alpine
+ image: apache/apisix:2.5-alpine
restart: always
volumes:
- ./apisix_config.yaml:/usr/local/apisix/conf/config.yaml:ro
@@ -148,7 +148,7 @@ services:
apisix2:
hostname: apisix_server2
- image: apache/apisix:2.4-alpine
+ image: apache/apisix:2.5-alpine
restart: always
volumes:
- ./apisix_config2.yaml:/usr/local/apisix/conf/config.yaml:ro
diff --git a/api/test/e2enew/schema/schema_test.go
b/api/test/e2enew/schema/schema_test.go
index 4f14d00..e856cc2 100644
--- a/api/test/e2enew/schema/schema_test.go
+++ b/api/test/e2enew/schema/schema_test.go
@@ -70,7 +70,7 @@ var _ = ginkgo.Describe("Schema Test", func() {
Path: "/apisix/admin/schemas/consumer",
Headers: map[string]string{"Authorization":
base.GetToken()},
ExpectStatus: http.StatusOK,
- ExpectBody:
`"properties":{"create_time":{"type":"integer"},"desc":{"maxLength":256,"type":"string"},"id":{"anyOf":[{"maxLength":64,"minLength":1,"pattern":"^[a-zA-Z0-9-_.]+$","type":"string"},{"minimum":1,"type":"integer"}]},"labels":{"description":"key/value
pairs to specify
attributes","maxProperties":16,"patternProperties":{".*":{"description":"value
of
label","maxLength":64,"minLength":1,"pattern":"^\\S+$","type":"string"}},"type":"object"},"plugins":{"type":"object"},"update_t
[...]
+ ExpectBody:
`"properties":{"create_time":{"type":"integer"},"desc":{"maxLength":256,"type":"string"},"labels":{"description":"key/value
pairs to specify
attributes","maxProperties":16,"patternProperties":{".*":{"description":"value
of
label","maxLength":64,"minLength":1,"pattern":"^\\S+$","type":"string"}},"type":"object"},"plugins":{"type":"object"},"update_time":{"type":"integer"},"username":{"maxLength":32,"minLength":1,"pattern":"^[a-zA-Z0-9_]+$","type":"string"}}`,
Sleep: base.SleepTime,
}),
table.Entry("get schema of non-existent resources",
base.HttpTestCase{
diff --git a/web/cypress/fixtures/plugin-dataset.json
b/web/cypress/fixtures/plugin-dataset.json
index b097ea8..5f3739a 100644
--- a/web/cypress/fixtures/plugin-dataset.json
+++ b/web/cypress/fixtures/plugin-dataset.json
@@ -280,7 +280,7 @@
}
},
{
- "shouldValid": false,
+ "shouldValid": true,
"data": {
"whitelist": ["jack1"],
"blacklist": ["jack2"]
@@ -1265,7 +1265,7 @@
}
},
{
- "shouldValid": false,
+ "shouldValid": true,
"data": {
"rules": [
{
diff --git
a/web/cypress/integration/consumer/create-upstream-with-cors-form.spec.js
b/web/cypress/integration/consumer/create-upstream-with-cors-form.spec.js
index 3bf2111..9afa316 100644
--- a/web/cypress/integration/consumer/create-upstream-with-cors-form.spec.js
+++ b/web/cypress/integration/consumer/create-upstream-with-cors-form.spec.js
@@ -25,7 +25,8 @@ context('Create and Delete Consumer', () => {
});
const selector = {
- max_age: "#max_age"
+ max_age: "#max_age",
+ allow_origins_by_regex: "#allow_origins_by_regex_0"
}
const data = {
@@ -44,7 +45,9 @@ context('Create and Delete Consumer', () => {
// config auth plugin
cy.contains(this.domSelector.pluginCard, 'key-auth').within(() => {
- cy.contains('Enable').click({ force: true });
+ cy.contains('Enable').click({
+ force: true
+ });
});
cy.focused(this.domSelector.drawer).should('exist');
cy.get(this.domSelector.disabledSwitcher).click().should('have.class',
'ant-switch-checked');
@@ -69,7 +72,7 @@ context('Create and Delete Consumer', () => {
cy.get(this.domSelector.drawer).should('be.visible');
cy.get(selector.max_age).clear();
- // config proxy-mirror form
+ // config cors form
cy.get(this.domSelector.drawer).within(() => {
cy.contains('Submit').click({
force: true,
@@ -79,6 +82,7 @@ context('Create and Delete Consumer', () => {
cy.get(this.domSelector.notificationCloseIcon).click().should('not.exist');
cy.get(selector.max_age).type(data.time);
+ cy.get(selector.allow_origins_by_regex).type('.*.test.com');
cy.get(this.domSelector.drawer).within(() => {
cy.contains('Submit').click({
force: true,
diff --git a/web/src/components/Plugin/PluginDetail.tsx
b/web/src/components/Plugin/PluginDetail.tsx
index 385f967..72c474b 100644
--- a/web/src/components/Plugin/PluginDetail.tsx
+++ b/web/src/components/Plugin/PluginDetail.tsx
@@ -285,6 +285,7 @@ const PluginDetail: React.FC<Props> = ({
title={formatMessage({ id:
'page.plugin.drawer.popconfirm.title.delete' })}
okText={formatMessage({ id: 'component.global.confirm' })}
cancelText={formatMessage({ id: 'component.global.cancel' })}
+ disabled={readonly}
onConfirm={() => {
onChange({
formData: form.getFieldsValue(),
@@ -294,13 +295,14 @@ const PluginDetail: React.FC<Props> = ({
}}
>
{initialData[name] ? (
- <Button key={3} type="primary" danger>
+ <Button key={3} type="primary" danger disabled={readonly}>
{formatMessage({ id: 'component.global.delete' })}
</Button>
) : null}
</Popconfirm>
<Button
key={2}
+ disabled={readonly}
type="primary"
onClick={() => {
try {
