diff --git a/.actions/openwhisk-utilities b/.actions/openwhisk-utilities deleted file mode 160000 index 8636f9ad3b..0000000000 --- a/.actions/openwhisk-utilities +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8636f9ad3bb7c4ed216f6b9291b0a6bf9a12cb76 diff --git a/.github/workflows/backend-e2e-test.yml b/.github/workflows/backend-e2e-test.yml index 5280edf8fa..8c70c69a1b 100644 --- a/.github/workflows/backend-e2e-test.yml +++ b/.github/workflows/backend-e2e-test.yml @@ -29,4 +29,4 @@ jobs: - name: run test working-directory: ./api/test/e2e - run: go test + run: go test -v diff --git a/.github/workflows/backend-unit-test.yml b/.github/workflows/backend-unit-test.yml index 202bf40224..40d7dbf0f6 100644 --- a/.github/workflows/backend-unit-test.yml +++ b/.github/workflows/backend-unit-test.yml @@ -51,7 +51,7 @@ jobs: export GO111MOUDULE=on export APISIX_CONF_PATH=$PWD/conf sed -i 's/9000/8088/' conf/conf.yaml - go build -o ./manager-api + go build -o ./manager-api ./cmd/manager ./manager-api > ./api.log 2>&1 & sleep 2 cat ./api.log diff --git a/.github/workflows/frontend-e2e-test.yml b/.github/workflows/frontend-e2e-test.yml index acedc21cad..a785058585 100644 --- a/.github/workflows/frontend-e2e-test.yml +++ b/.github/workflows/frontend-e2e-test.yml @@ -41,7 +41,7 @@ jobs: - name: Start manager-api working-directory: ./api - run: nohup go run . & + run: nohup go run ./cmd/manager & - name: Install front-end dependencies run: yarn install diff --git a/.github/workflows/spellchecker.yml b/.github/workflows/spellchecker.yml new file mode 100644 index 0000000000..6b246517f8 --- /dev/null +++ b/.github/workflows/spellchecker.yml @@ -0,0 +1,21 @@ +name: spellchecker +on: + pull_request: + branches: + - master +jobs: + misspell: + name: runner/misspell + runs-on: ubuntu-latest + steps: + - name: Check out code. + uses: actions/checkout@v1 + - name: Install + run: | + wget -O - -q https://git.io/misspell | sh -s -- -b . + - name: Misspell + run: | + find . -type f -maxdepth 1 | xargs ./misspell -error + find . -name "*.go" -type f | xargs ./misspell -error + find docs -type f | xargs ./misspell -error + find web/src web/cypress -type f | xargs ./misspell -error diff --git a/Dockerfile b/Dockerfile index fedbc88605..c9e3dde938 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,7 +45,7 @@ RUN wget https://github.com/api7/dag-to-lua/archive/v1.1.tar.gz -O /tmp/v1.1.tar RUN if [ "$ENABLE_PROXY" = "true" ] ; then go env -w GOPROXY=https://goproxy.io,direct ; fi RUN go env -w GO111MODULE=on \ - && CGO_ENABLED=0 go build -o ../output/manager-api . + && CGO_ENABLED=0 go build -o ../output/manager-api ./cmd/manager FROM node:14-alpine as fe-builder diff --git a/Makefile b/Makefile index 6877b98247..f8f1fc4b3b 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ api-test: api-default ### api-run: Run the manager-api .PHONY: api-run api-run: api-default - cd api/ && go run . + cd api/ && go run ./cmd/manager ### api-stop: Stop the manager-api api-stop: diff --git a/api/README.md b/api/README.md index eab5c4026b..5fcf1f869d 100644 --- a/api/README.md +++ b/api/README.md @@ -24,3 +24,26 @@ This is a backend project which the dashboard depends on, implemented by Golang. ## Installation [Please refer to the doc](../README.md) + +## Project structure + +```text +├── README.md +├── VERSION +├── build-tools +├── build.sh +├── cmd +├── conf +├── entry.sh +├── go.mod +├── go.sum +├── internal +├── run.sh +└── test +``` + +1. The `cmd` directory is the project entrance. +2. The `internal` directory contains the main logic of manager-api. +3. The `conf` directory contains the default configuration file. +4. The `test` directory contains E2E test cases. + diff --git a/api/build.sh b/api/build.sh index 3d41e89e8b..972177a282 100755 --- a/api/build.sh +++ b/api/build.sh @@ -31,7 +31,7 @@ if [[ ! -f "dag-to-lua-1.1/lib/dag-to-lua.lua" ]]; then fi # build -cd ./api && go build -o ../output/manager-api -ldflags "-X main.Version=${VERSION}" . && cd .. +cd ./api && go build -o ../output/manager-api -ldflags "-X github.com/apisix/manager-api/cmd.Version=${VERSION}" ./cmd/manager && cd .. cp ./api/conf/schema.json ./output/conf/schema.json cp ./api/conf/conf.yaml ./output/conf/conf.yaml diff --git a/api/cmd/manager/main.go b/api/cmd/manager/main.go new file mode 100644 index 0000000000..b4f260aa0a --- /dev/null +++ b/api/cmd/manager/main.go @@ -0,0 +1,30 @@ +/* + * 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 main + +import ( + "fmt" + "os" + + "github.com/apisix/manager-api/cmd" +) + +func main() { + if err := cmd.NewManagerAPICommand().Execute(); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + } +} diff --git a/api/cmd/managerapi.go b/api/cmd/managerapi.go new file mode 100644 index 0000000000..23cad0dd90 --- /dev/null +++ b/api/cmd/managerapi.go @@ -0,0 +1,116 @@ +/* + * 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 cmd + +import ( + "context" + "fmt" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "github.com/apisix/manager-api/internal" + "github.com/apisix/manager-api/internal/conf" + "github.com/apisix/manager-api/internal/core/storage" + "github.com/apisix/manager-api/internal/core/store" + "github.com/apisix/manager-api/internal/handler" + "github.com/apisix/manager-api/internal/log" + "github.com/apisix/manager-api/internal/utils" + "github.com/shiningrush/droplet" + "github.com/spf13/cobra" +) + +var Version string + +func printInfo() { + fmt.Fprint(os.Stdout, "The manager-api is running successfully!\n\n") + fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Version", Version) + fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "Listen", conf.ServerHost, conf.ServerPort) + fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Loglevel", conf.ErrorLogLevel) + fmt.Fprintf(os.Stdout, "%-8s: %s\n\n", "Logfile", conf.ErrorLogPath) +} + +// NewManagerAPICommand creates the manager-api command. +func NewManagerAPICommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "manager-api [flags]", + Short: "APISIX Manager API", + RunE: func(cmd *cobra.Command, args []string) error { + conf.InitConf() + droplet.Option.Orchestrator = func(mws []droplet.Middleware) []droplet.Middleware { + var newMws []droplet.Middleware + // default middleware order: resp_reshape, auto_input, traffic_log + // We should put err_transform at second to catch all error + newMws = append(newMws, mws[0], &handler.ErrorTransformMiddleware{}) + newMws = append(newMws, mws[1:]...) + return newMws + } + + if err := storage.InitETCDClient(conf.ETCDConfig); err != nil { + log.Errorf("init etcd client fail: %w", err) + panic(err) + } + if err := store.InitStores(); err != nil { + log.Errorf("init stores fail: %w", err) + panic(err) + } + // routes + r := internal.SetUpRouter() + addr := fmt.Sprintf("%s:%d", conf.ServerHost, conf.ServerPort) + s := &http.Server{ + Addr: addr, + Handler: r, + ReadTimeout: time.Duration(1000) * time.Millisecond, + WriteTimeout: time.Duration(5000) * time.Millisecond, + } + + log.Infof("The Manager API is listening on %s", addr) + + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + + go func() { + if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { + utils.CloseAll() + log.Fatalf("listen and serv fail: %s", err) + } + }() + + printInfo() + + sig := <-quit + log.Infof("The Manager API server receive %s and start shutting down", sig.String()) + + ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) + defer cancel() + + if err := s.Shutdown(ctx); err != nil { + log.Errorf("Shutting down server error: %s", err) + } + + log.Infof("The Manager API server exited") + + utils.CloseAll() + return nil + }, + } + + cmd.PersistentFlags().StringVarP(&conf.WorkDir, "work-dir", "p", ".", "current work directory") + return cmd +} diff --git a/api/conf/schema.json b/api/conf/schema.json index 76560bbfa3..cf0a89152c 100644 --- a/api/conf/schema.json +++ b/api/conf/schema.json @@ -72,50 +72,6 @@ "required": ["plugins"], "type": "object" }, - "host_def": { - "pattern": "^\\*?[0-9a-zA-Z-.]+$", - "type": "string" - }, - "id_schema": { - "anyOf": [{ - "maxLength": 64, - "minLength": 1, - "pattern": "^[a-zA-Z0-9-_.]+$", - "type": "string" - }, { - "minimum": 1, - "type": "integer" - }] - }, - "ip_def": [{ - "format": "ipv4", - "title": "IPv4", - "type": "string" - }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", - "title": "IPv4/CIDR", - "type": "string" - }, { - "format": "ipv6", - "title": "IPv6", - "type": "string" - }, { - "pattern": "^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?/[0-9]{1,3}$", - "title": "IPv6/CIDR", - "type": "string" - }], - "label_value_def": { - "description": "value of label", - "maxLength": 64, - "minLength": 1, - "pattern": "^[a-zA-Z0-9-_.]+$", - "type": "string" - }, - "plugin_disable_schema": { - "disable": { - "type": "boolean" - } - }, "plugins": { "items": { "properties": { @@ -290,7 +246,7 @@ "title": "IPv4", "type": "string" }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", + "pattern": "^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([12]?[0-9]|3[0-2])$", "title": "IPv4/CIDR", "type": "string" }, { @@ -312,7 +268,7 @@ "title": "IPv4", "type": "string" }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", + "pattern": "^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([12]?[0-9]|3[0-2])$", "title": "IPv4/CIDR", "type": "string" }, { @@ -677,7 +633,6 @@ "required": ["host", "port", "weight"], "type": "object" }, - "minItems": 1, "type": "array" }] }, @@ -1146,7 +1101,6 @@ "required": ["host", "port", "weight"], "type": "object" }, - "minItems": 1, "type": "array" }] }, @@ -1329,7 +1283,7 @@ "title": "IPv4", "type": "string" }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", + "pattern": "^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([12]?[0-9]|3[0-2])$", "title": "IPv4/CIDR", "type": "string" }, { @@ -1350,7 +1304,7 @@ "title": "IPv4", "type": "string" }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", + "pattern": "^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([12]?[0-9]|3[0-2])$", "title": "IPv4/CIDR", "type": "string" }, { @@ -1687,7 +1641,6 @@ "required": ["host", "port", "weight"], "type": "object" }, - "minItems": 1, "type": "array" }] }, @@ -2071,7 +2024,6 @@ "required": ["host", "port", "weight"], "type": "object" }, - "minItems": 1, "type": "array" }] }, @@ -2123,22 +2075,18 @@ }, "type": "object" }, - "upstream_hash_header_schema": { - "pattern": "^[a-zA-Z0-9-_]+$", - "type": "string" - }, - "upstream_hash_vars_schema": { - "pattern": "^((uri|server_name|server_addr|request_uri|remote_port|remote_addr|query_string|host|hostname)|arg_[0-9a-zA-z_-]+)$", - "type": "string" - }, - "uri_def": { - "pattern": "^[^\\/]+:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?", - "type": "string" - }, - "version": 0.5 + "upstream_hash_header_schema": { + "pattern": "^[a-zA-Z0-9-_]+$", + "type": "string" + }, + "upstream_hash_vars_schema": { + "pattern": "^((uri|server_name|server_addr|request_uri|remote_port|remote_addr|query_string|host|hostname)|arg_[0-9a-zA-z_-]+)$", + "type": "string" + } }, "plugins": { "api-breaker": { + "priority": 1005, "schema": { "properties": { "break_response_code": { @@ -2204,9 +2152,11 @@ }, "required": ["break_response_code"], "type": "object" - } + }, + "version": 0.1 }, "authz-keycloak": { + "priority": 2000, "schema": { "properties": { "audience": { @@ -2266,7 +2216,8 @@ }, "required": ["token_endpoint"], "type": "object" - } + }, + "version": 0.1 }, "basic-auth": { "consumer_schema": { @@ -2283,20 +2234,47 @@ "title": "work with consumer object", "type": "object" }, + "priority": 2520, "schema": { "additionalProperties": false, - "properties": {}, + "properties": { + "disable": { + "type": "boolean" + } + }, "title": "work with route or service object", "type": "object" - } + }, + "type": "auth", + "version": 0.1 }, "batch-requests": { + "metadata_schema": { + "additionalProperties": false, + "properties": { + "max_body_size": { + "default": 1048576, + "description": "max pipeline body size in bytes", + "exclusiveMinimum": 0, + "type": "integer" + } + }, + "type": "object" + }, + "priority": 4010, "schema": { "additionalProperties": false, + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "version": 0.1 }, "consumer-restriction": { + "priority": 2400, "schema": { "oneOf": [{ "properties": { @@ -2343,10 +2321,17 @@ "required": ["whitelist"], "title": "whitelist" }], + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "version": 0.1 }, "cors": { + "priority": 4000, "schema": { "properties": { "allow_credential": { @@ -2381,9 +2366,11 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "echo": { + "priority": 412, "schema": { "additionalProperties": false, "anyOf": [{ @@ -2418,34 +2405,80 @@ } }, "type": "object" - } + }, + "version": 0.1 }, - "example-plugin": { - "schema": { + "error-log-logger": { + "metadata_schema": { "properties": { - "i": { + "batch_max_size": { + "default": 1000, "minimum": 0, - "type": "number" + "type": "integer" + }, + "buffer_duration": { + "default": 60, + "minimum": 1, + "type": "integer" }, - "ip": { + "host": { + "pattern": "^\\*?[0-9a-zA-Z-.]+$", "type": "string" }, - "port": { + "inactive_timeout": { + "default": 3, + "minimum": 1, "type": "integer" }, - "s": { + "keepalive": { + "default": 30, + "minimum": 1, + "type": "integer" + }, + "level": { + "default": "WARN", + "enum": ["ALERT", "CRIT", "DEBUG", "EMERG", "ERR", "ERROR", "INFO", "NOTICE", "STDERR", "WARN"], "type": "string" }, - "t": { - "minItems": 1, - "type": "array" + "max_retry_count": { + "default": 0, + "minimum": 0, + "type": "integer" + }, + "name": { + "default": "error-log-logger", + "type": "string" + }, + "port": { + "minimum": 0, + "type": "integer" + }, + "retry_delay": { + "default": 1, + "minimum": 0, + "type": "integer" + }, + "timeout": { + "default": 3, + "minimum": 1, + "type": "integer" + }, + "tls": { + "default": false, + "type": "boolean" + }, + "tls_server_name": { + "type": "string" } }, - "required": ["i"], + "required": ["host", "port"], "type": "object" - } + }, + "priority": 1091, + "version": 0.1 }, "fault-injection": { + "priority": 11000, "schema": { "minProperties": 1, "properties": { @@ -2485,9 +2518,11 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "grpc-transcode": { + "priority": 506, "schema": { "additionalProperties": true, "properties": { @@ -2542,7 +2577,8 @@ }, "required": ["method", "proto_id", "service"], "type": "object" - } + }, + "version": 0.1 }, "hmac-auth": { "consumer_schema": { @@ -2590,14 +2626,36 @@ "title": "work with consumer object", "type": "object" }, + "priority": 2530, "schema": { "additionalProperties": false, - "properties": {}, + "properties": { + "disable": { + "type": "boolean" + } + }, "title": "work with route or service object", "type": "object" - } + }, + "type": "auth", + "version": 0.1 }, "http-logger": { + "metadata_schema": { + "additionalProperties": false, + "properties": { + "log_format": { + "default": { + "@timestamp": "$time_iso8601", + "client_ip": "$remote_addr", + "host": "$host" + }, + "type": "object" + } + }, + "type": "object" + }, + "priority": 410, "schema": { "properties": { "auth_header": { @@ -2654,9 +2712,11 @@ }, "required": ["uri"], "type": "object" - } + }, + "version": 0.1 }, "ip-restriction": { + "priority": 3000, "schema": { "oneOf": [{ "additionalProperties": false, @@ -2668,7 +2728,7 @@ "title": "IPv4", "type": "string" }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", + "pattern": "^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([12]?[0-9]|3[0-2])$", "title": "IPv4/CIDR", "type": "string" }, { @@ -2697,7 +2757,7 @@ "title": "IPv4", "type": "string" }, { - "pattern": "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/[0-9]{1,2}$", + "pattern": "^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([12]?[0-9]|3[0-2])$", "title": "IPv4/CIDR", "type": "string" }, { @@ -2717,12 +2777,42 @@ "required": ["blacklist"], "title": "blacklist" }], + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "version": 0.1 }, "jwt-auth": { "consumer_schema": { - "additionalProperties": false, + "dependencies": { + "algorithm": { + "oneOf": [{ + "properties": { + "algorithm": { + "default": "HS256", + "enum": ["HS256", "HS512"] + } + } + }, { + "properties": { + "algorithm": { + "enum": ["RS256"] + }, + "private_key": { + "type": "string" + }, + "public_key": { + "type": "string" + } + }, + "required": ["private_key", "public_key"] + }] + } + }, "properties": { "algorithm": { "default": "HS256", @@ -2741,12 +2831,6 @@ "key": { "type": "string" }, - "private_key": { - "type": "string" - }, - "public_key": { - "type": "string" - }, "secret": { "type": "string" } @@ -2754,13 +2838,21 @@ "required": ["key"], "type": "object" }, + "priority": 2510, "schema": { "additionalProperties": false, - "properties": {}, + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "type": "auth", + "version": 0.1 }, "kafka-logger": { + "priority": 403, "schema": { "properties": { "batch_max_size": { @@ -2818,7 +2910,8 @@ }, "required": ["broker_list", "kafka_topic"], "type": "object" - } + }, + "version": 0.1 }, "key-auth": { "consumer_schema": { @@ -2831,13 +2924,21 @@ "required": ["key"], "type": "object" }, + "priority": 2500, "schema": { "additionalProperties": false, - "properties": {}, + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "type": "auth", + "version": 0.1 }, "limit-conn": { + "priority": 1003, "schema": { "properties": { "burst": { @@ -2864,9 +2965,11 @@ }, "required": ["burst", "conn", "default_conn_delay", "key"], "type": "object" - } + }, + "version": 0.1 }, "limit-count": { + "priority": 1002, "schema": { "dependencies": { "policy": { @@ -2957,9 +3060,11 @@ }, "required": ["count", "time_window"], "type": "object" - } + }, + "version": 0.4 }, "limit-req": { + "priority": 1001, "schema": { "properties": { "burst": { @@ -2982,25 +3087,68 @@ }, "required": ["burst", "key", "rate"], "type": "object" - } + }, + "version": 0.1 }, "log-rotate": { + "priority": 100, "schema": { "additionalProperties": false, - "properties": {}, + "properties": { + "disable": { + "type": "boolean" + } + }, + "type": "object" + }, + "version": 0.1 + }, + "mqtt-proxy": { + "priority": 1000, + "schema": { + "properties": { + "protocol_level": { + "type": "integer" + }, + "protocol_name": { + "type": "string" + }, + "upstream": { + "properties": { + "ip": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + } + }, + "required": ["protocol_level", "protocol_name", "upstream"], "type": "object" - } + }, + "version": 0.1 }, "node-status": { + "priority": 1000, "schema": { "additionalProperties": false, + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "version": 0.1 }, "openid-connect": { + "priority": 2599, "schema": { "properties": { "bearer_only": { + "default": false, "type": "boolean" }, "client_id": { @@ -3016,27 +3164,35 @@ "type": "string" }, "introspection_endpoint_auth_method": { + "default": "client_secret_basic", "type": "string" }, "logout_path": { + "default": "/logout", "type": "string" }, "public_key": { "type": "string" }, "realm": { + "default": "apisix", "type": "string" }, "redirect_uri": { + "description": "use ngx.var.request_uri if not configured", "type": "string" }, "scope": { + "default": "openid", "type": "string" }, "ssl_verify": { + "default": false, "type": "boolean" }, "timeout": { + "default": 3, + "description": "timeout in seconds", "minimum": 1, "type": "integer" }, @@ -3046,15 +3202,24 @@ }, "required": ["client_id", "client_secret", "discovery"], "type": "object" - } + }, + "version": 0.1 }, "prometheus": { + "priority": 500, "schema": { "additionalProperties": false, + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "version": 0.2 }, "proxy-cache": { + "priority": 1009, "schema": { "properties": { "cache_bypass": { @@ -3118,9 +3283,11 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "proxy-mirror": { + "priority": 1010, "schema": { "minProperties": 1, "properties": { @@ -3131,9 +3298,11 @@ }, "required": ["host"], "type": "object" - } + }, + "version": 0.1 }, "proxy-rewrite": { + "priority": 1008, "schema": { "additionalProperties": false, "minProperties": 1, @@ -3172,9 +3341,11 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "redirect": { + "priority": 900, "schema": { "oneOf": [{ "required": ["uri"] @@ -3192,13 +3363,16 @@ }, "uri": { "minLength": 2, + "pattern": "(\\\\\\$[0-9a-zA-Z_]+)|\\$\\{([0-9a-zA-Z_]+)\\}|\\$([0-9a-zA-Z_]+)|(\\$|[^$\\\\]+)", "type": "string" } }, "type": "object" - } + }, + "version": 0.1 }, "referer-restriction": { + "priority": 2990, "schema": { "additionalProperties": false, "properties": { @@ -3217,9 +3391,11 @@ }, "required": ["whitelist"], "type": "object" - } + }, + "version": 0.1 }, "request-id": { + "priority": 11010, "schema": { "properties": { "header_name": { @@ -3232,9 +3408,11 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "request-validation": { + "priority": 2800, "schema": { "anyOf": [{ "properties": { @@ -3253,10 +3431,18 @@ "required": ["header_schema"], "title": "Header schema" }], + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "type": "validation", + "version": 0.1 }, "response-rewrite": { + "priority": 899, "schema": { "additionalProperties": false, "minProperties": 1, @@ -3283,15 +3469,24 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "server-info": { + "priority": 990, "schema": { "additionalProperties": false, + "properties": { + "disable": { + "type": "boolean" + } + }, "type": "object" - } + }, + "version": 0.1 }, "serverless-post-function": { + "priority": -2000, "schema": { "properties": { "functions": { @@ -3302,15 +3497,18 @@ "type": "array" }, "phase": { + "default": "access", "enum": ["access", "balancer", "body_filter", "header_filter", "log", "rewrite"], "type": "string" } }, "required": ["functions"], "type": "object" - } + }, + "version": 0.1 }, "serverless-pre-function": { + "priority": 10000, "schema": { "properties": { "functions": { @@ -3321,15 +3519,38 @@ "type": "array" }, "phase": { + "default": "access", "enum": ["access", "balancer", "body_filter", "header_filter", "log", "rewrite"], "type": "string" } }, "required": ["functions"], "type": "object" - } + }, + "version": 0.1 }, "skywalking": { + "metadata_schema": { + "additionalProperties": false, + "properties": { + "endpoint_addr": { + "default": "http://127.0.0.1:12800", + "type": "string" + }, + "service_instance_name": { + "default": "APISIX Instance Name", + "description": "User Service Instance Name", + "type": "string" + }, + "service_name": { + "default": "APISIX", + "description": "service name for skywalking", + "type": "string" + } + }, + "type": "object" + }, + "priority": -1100, "schema": { "additionalProperties": false, "properties": { @@ -3341,9 +3562,11 @@ } }, "type": "object" - } + }, + "version": 0.1 }, "sls-logger": { + "priority": 406, "schema": { "properties": { "access_key_id": { @@ -3405,9 +3628,11 @@ }, "required": ["access_key_id", "access_key_secret", "host", "logstore", "port", "project"], "type": "object" - } + }, + "version": 0.1 }, "syslog": { + "priority": 401, "schema": { "properties": { "batch_max_size": { @@ -3475,9 +3700,11 @@ }, "required": ["host", "port"], "type": "object" - } + }, + "version": 0.1 }, "tcp-logger": { + "priority": 405, "schema": { "properties": { "batch_max_size": { @@ -3535,9 +3762,11 @@ }, "required": ["host", "port"], "type": "object" - } + }, + "version": 0.1 }, "udp-logger": { + "priority": 400, "schema": { "properties": { "batch_max_size": { @@ -3578,9 +3807,11 @@ }, "required": ["host", "port"], "type": "object" - } + }, + "version": 0.1 }, "uri-blocker": { + "priority": 2900, "schema": { "properties": { "block_rules": { @@ -3600,9 +3831,11 @@ }, "required": ["block_rules"], "type": "object" - } + }, + "version": 0.1 }, "wolf-rbac": { + "priority": 2555, "schema": { "properties": { "appid": { @@ -3619,9 +3852,12 @@ } }, "type": "object" - } + }, + "type": "auth", + "version": 0.1 }, "zipkin": { + "priority": 11011, "schema": { "properties": { "endpoint": { @@ -3645,7 +3881,8 @@ }, "required": ["endpoint", "sample_ratio"], "type": "object" - } + }, + "version": 0.1 } } } \ No newline at end of file diff --git a/api/go.mod b/api/go.mod index 96561d8d2b..1712f04157 100644 --- a/api/go.mod +++ b/api/go.mod @@ -4,33 +4,44 @@ go 1.13 replace google.golang.org/grpc => google.golang.org/grpc v1.26.0 +replace github.com/coreos/bbolt => go.etcd.io/bbolt v1.3.5 + require ( github.com/api7/go-jsonpatch v0.0.0-20180223123257-a8710867776e + github.com/cameront/go-jsonpatch v0.0.0-20180223123257-a8710867776e // indirect + github.com/coreos/bbolt v0.0.0-00010101000000-000000000000 // indirect github.com/coreos/etcd v3.3.25+incompatible // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/dustin/go-humanize v1.0.0 // indirect github.com/evanphx/json-patch/v5 v5.1.0 github.com/gin-contrib/pprof v1.3.0 github.com/gin-contrib/sessions v0.0.3 github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e github.com/gin-gonic/gin v1.6.3 github.com/gogo/protobuf v1.3.1 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/google/uuid v1.1.2 // indirect - github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible - github.com/lestrrat-go/strftime v1.0.3 // indirect - github.com/natefinch/lumberjack v2.0.0+incompatible + github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/prometheus/client_golang v1.8.0 // indirect github.com/satori/go.uuid v1.2.0 github.com/shiningrush/droplet v0.2.3 github.com/shiningrush/droplet/wrapper/gin v0.2.0 - github.com/sirupsen/logrus v1.7.0 + github.com/sirupsen/logrus v1.7.0 // indirect github.com/sony/sonyflake v1.0.0 + github.com/spf13/cobra v0.0.3 github.com/stretchr/testify v1.6.1 github.com/tidwall/gjson v1.6.1 + github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 // indirect github.com/xeipuuv/gojsonschema v1.2.0 github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da go.etcd.io/etcd v3.3.25+incompatible go.uber.org/zap v1.16.0 + golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect gopkg.in/yaml.v2 v2.3.0 + sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/api/go.sum b/api/go.sum index d29bd105f6..6598e30efe 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,33 +1,88 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/api7/go-jsonpatch v0.0.0-20180223123257-a8710867776e h1:TX/8xM53DHaIIBr4wU+ifYI8IkUzS8+HrX8kzIzaaG0= github.com/api7/go-jsonpatch v0.0.0-20180223123257-a8710867776e/go.mod h1:yc49guNPyTy2deyszk3erQN+2vO2NwLKPNicXurj7Hs= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw= github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI= +github.com/cameront/go-jsonpatch v0.0.0-20180223123257-a8710867776e h1:6c3+GQuYUWljNcReOg4gxMUss9Gjll+5Y9vqDM+ILy8= +github.com/cameront/go-jsonpatch v0.0.0-20180223123257-a8710867776e/go.mod h1:kdPJxKAfR3ZdD+MWYorN1oTdV9+qwJy9jO/0meJmcxU= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/etcd v3.3.25+incompatible h1:0GQEw6h3YnuOVdtwygkIfJ+Omx0tZ8/QkVyXI4LkbeY= github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch/v5 v5.1.0 h1:B0aXl1o/1cP8NbviYiBMkcHBtUjIJ1/Ccg6b+SwCLQg= github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 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/sessions v0.0.3 h1:PoBXki+44XdJdlgDqDrY5nDVe3Wk7wDV/UCOuLP6fBI= @@ -41,6 +96,14 @@ github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv 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/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= @@ -51,11 +114,22 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o= github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -66,75 +140,232 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.1.3 h1:uXoZdcdA5XdXF3QzuSlheVRUvjl+1rKY7zBXL68L9RU= github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= -github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= -github.com/lestrrat-go/strftime v1.0.3 h1:qqOPU7y+TM8Y803I8fG9c/DyKG3xH/xkng6keC1015Q= -github.com/lestrrat-go/strftime v1.0.3/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/memcachier/mc v2.0.1+incompatible/go.mod h1:7bkvFE61leUBvXz+yxsOnGBQSZpBSPIMUQSmmSHvuXc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= -github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/quasoft/memstore v0.0.0-20180925164028-84a050167438/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shiningrush/droplet v0.0.0-20191118073048-00b06fe19ce4/go.mod h1:E/th13n/wtPi+Cj2f0hAAEFeT3gb5xsS6Ob4WRrdxdM= -github.com/shiningrush/droplet v0.2.1 h1:p2utttTbCfgiL+x0Zrb2jFeWspB7/o+v3e+R94G6nm4= -github.com/shiningrush/droplet v0.2.1/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M= -github.com/shiningrush/droplet v0.2.2 h1:jEqSGoJXlybt1yQdauu+waE+l7KYlguNs8VayMfQ96Q= -github.com/shiningrush/droplet v0.2.2/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M= github.com/shiningrush/droplet v0.2.3 h1:bzPDzkE0F54r94XsultGS8uAPeL3pZIRmjqM0zIlpeI= github.com/shiningrush/droplet v0.2.3/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M= github.com/shiningrush/droplet/wrapper/gin v0.2.0 h1:LHkU+TbSkpePgXrTg3hJoSZlCMS03GeWMl0t+oLkd44= github.com/shiningrush/droplet/wrapper/gin v0.2.0/go.mod h1:ZJu+sCRrVXn5Pg618c1KK3Ob2UiXGuPM1ROx5uMM9YQ= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM= github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -146,66 +377,171 @@ github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 h1:j6JEOq5QWFker+d7mFQYOhjTZonQ7YkLTHm56dbn+yM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da h1:NimzV1aGyq29m5ukMK0AMWEhFaL/lrEOaephfuoiARg= github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= +go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v3.3.25+incompatible h1:V1RzkZJj9LqsJRy+TUBgpWSbZXITLB819lstuTFoZOY= go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b h1:GgiSbuUyC0BlbUmHQBgFqu32eiRR/CEYdjOjOd4zE6Y= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 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= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= @@ -220,12 +556,27 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -233,4 +584,9 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/api/conf/conf.go b/api/internal/conf/conf.go similarity index 98% rename from api/conf/conf.go rename to api/internal/conf/conf.go index 62617740a4..76230d31f0 100644 --- a/api/conf/conf.go +++ b/api/internal/conf/conf.go @@ -17,7 +17,6 @@ package conf import ( - "flag" "fmt" "io/ioutil" "log" @@ -105,13 +104,11 @@ type Config struct { func init() { InitConf() } + func InitConf() { //go test if workDir := os.Getenv("APISIX_API_WORKDIR"); workDir != "" { WorkDir = workDir - } else { - flag.StringVar(&WorkDir, "p", ".", "current work dir") - flag.Parse() } setConf() diff --git a/api/internal/core/entity/entity.go b/api/internal/core/entity/entity.go index 1af128e5a4..0e68078bd8 100644 --- a/api/internal/core/entity/entity.go +++ b/api/internal/core/entity/entity.go @@ -52,6 +52,12 @@ func (info *BaseInfo) Updating(storedInfo *BaseInfo) { info.UpdateTime = time.Now().Unix() } +func (info *BaseInfo) KeyCompat(key string) { + if info.ID == nil && key != "" { + info.ID = key + } +} + type BaseInfoSetter interface { GetBaseInfo() *BaseInfo } diff --git a/api/internal/core/entity/format.go b/api/internal/core/entity/format.go index 4953b3a30a..d92bb40594 100644 --- a/api/internal/core/entity/format.go +++ b/api/internal/core/entity/format.go @@ -20,7 +20,7 @@ import ( "net" "strconv" - "github.com/apisix/manager-api/log" + "github.com/apisix/manager-api/internal/log" ) func mapKV2Node(key string, val float64) (*Node, error) { diff --git a/api/internal/core/storage/etcd.go b/api/internal/core/storage/etcd.go index f378ba4e1c..fb879b3e30 100644 --- a/api/internal/core/storage/etcd.go +++ b/api/internal/core/storage/etcd.go @@ -23,9 +23,9 @@ import ( "go.etcd.io/etcd/clientv3" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" + "github.com/apisix/manager-api/internal/log" "github.com/apisix/manager-api/internal/utils" - "github.com/apisix/manager-api/log" ) var ( @@ -73,15 +73,19 @@ func (s *EtcdV3Storage) Get(ctx context.Context, key string) (string, error) { return string(resp.Kvs[0].Value), nil } -func (s *EtcdV3Storage) List(ctx context.Context, key string) ([]string, error) { +func (s *EtcdV3Storage) List(ctx context.Context, key string) ([]Keypair, error) { resp, err := Client.Get(ctx, key, clientv3.WithPrefix()) if err != nil { log.Errorf("etcd get failed: %s", err) return nil, fmt.Errorf("etcd get failed: %s", err) } - var ret []string + var ret []Keypair for i := range resp.Kvs { - ret = append(ret, string(resp.Kvs[i].Value)) + data := Keypair{ + Key: string(resp.Kvs[i].Key), + Value: string(resp.Kvs[i].Value), + } + ret = append(ret, data) } return ret, nil diff --git a/api/internal/core/storage/storage.go b/api/internal/core/storage/storage.go index c4b5399b47..ba307720d1 100644 --- a/api/internal/core/storage/storage.go +++ b/api/internal/core/storage/storage.go @@ -20,7 +20,7 @@ import "context" type Interface interface { Get(ctx context.Context, key string) (string, error) - List(ctx context.Context, key string) ([]string, error) + List(ctx context.Context, key string) ([]Keypair, error) Create(ctx context.Context, key, val string) error Update(ctx context.Context, key, val string) error BatchDelete(ctx context.Context, keys []string) error @@ -33,6 +33,11 @@ type WatchResponse struct { Canceled bool } +type Keypair struct { + Key string + Value string +} + type Event struct { Type EventType Key string diff --git a/api/internal/core/storage/storage_mock.go b/api/internal/core/storage/storage_mock.go index c5063a9e52..f85d8b76b0 100644 --- a/api/internal/core/storage/storage_mock.go +++ b/api/internal/core/storage/storage_mock.go @@ -1,5 +1,19 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. - +/* + * 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 storage import ( @@ -63,15 +77,15 @@ func (_m *MockInterface) Get(ctx context.Context, key string) (string, error) { } // List provides a mock function with given fields: ctx, key -func (_m *MockInterface) List(ctx context.Context, key string) ([]string, error) { +func (_m *MockInterface) List(ctx context.Context, key string) ([]Keypair, error) { ret := _m.Called(ctx, key) - var r0 []string - if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok { + var r0 []Keypair + if rf, ok := ret.Get(0).(func(context.Context, string) []Keypair); ok { r0 = rf(ctx, key) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) + r0 = ret.Get(0).([]Keypair) } } diff --git a/api/internal/core/store/query.go b/api/internal/core/store/query.go index 20036d06ab..e4c27c1c2f 100644 --- a/api/internal/core/store/query.go +++ b/api/internal/core/store/query.go @@ -16,7 +16,7 @@ package store import ( "github.com/apisix/manager-api/internal/core/entity" - "github.com/apisix/manager-api/log" + "github.com/apisix/manager-api/internal/log" ) type Query struct { diff --git a/api/internal/core/store/store.go b/api/internal/core/store/store.go index ee3fa5038e..9a4b11314a 100644 --- a/api/internal/core/store/store.go +++ b/api/internal/core/store/store.go @@ -30,8 +30,8 @@ import ( "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/storage" + "github.com/apisix/manager-api/internal/log" "github.com/apisix/manager-api/internal/utils" - "github.com/apisix/manager-api/log" ) type Interface interface { @@ -96,13 +96,15 @@ func (s *GenericStore) Init() error { return err } for i := range ret { - if ret[i] == "init_dir" { + if ret[i].Value == "init_dir" { continue } - objPtr, err := s.StringToObjPtr(ret[i]) + key := ret[i].Key[len(s.opt.BasePath)+1:] + objPtr, err := s.StringToObjPtr(ret[i].Value, key) if err != nil { return err } + s.cache.Store(s.opt.KeyFunc(objPtr), objPtr) } @@ -117,12 +119,13 @@ func (s *GenericStore) Init() error { for i := range event.Events { switch event.Events[i].Type { case storage.EventTypePut: - objPtr, err := s.StringToObjPtr(event.Events[i].Value) + key := event.Events[i].Key[len(s.opt.BasePath)+1:] + objPtr, err := s.StringToObjPtr(event.Events[i].Value, key) if err != nil { log.Warnf("value convert to obj failed: %s", err) continue } - s.cache.Store(event.Events[i].Key[len(s.opt.BasePath)+1:], objPtr) + s.cache.Store(key, objPtr) case storage.EventTypeDelete: s.cache.Delete(event.Events[i].Key[len(s.opt.BasePath)+1:]) } @@ -320,15 +323,21 @@ func (s *GenericStore) Close() error { return nil } -func (s *GenericStore) StringToObjPtr(str string) (interface{}, error) { +func (s *GenericStore) StringToObjPtr(str, key string) (interface{}, error) { objPtr := reflect.New(s.opt.ObjType) - err := json.Unmarshal([]byte(str), objPtr.Interface()) + ret := objPtr.Interface() + err := json.Unmarshal([]byte(str), ret) if err != nil { log.Errorf("json marshal failed: %s", err) return nil, fmt.Errorf("json unmarshal failed: %s", err) } - return objPtr.Interface(), nil + if setter, ok := ret.(entity.BaseInfoSetter); ok { + info := setter.GetBaseInfo() + info.KeyCompat(key) + } + + return ret, nil } func (s *GenericStore) GetObjStorageKey(obj interface{}) string { diff --git a/api/internal/core/store/store_test.go b/api/internal/core/store/store_test.go index 20c5f7bfeb..9bc1159c34 100644 --- a/api/internal/core/store/store_test.go +++ b/api/internal/core/store/store_test.go @@ -115,7 +115,7 @@ func TestGenericStore_Init(t *testing.T) { caseDesc string giveStore *GenericStore giveListErr error - giveListRet []string + giveListRet []storage.Keypair giveWatchCh chan storage.WatchResponse giveResp storage.WatchResponse wantErr error @@ -134,9 +134,15 @@ func TestGenericStore_Init(t *testing.T) { }, }, }, - giveListRet: []string{ - `{"Field1":"demo1-f1", "Field2":"demo1-f2"}`, - `{"Field1":"demo2-f1", "Field2":"demo2-f2"}`, + giveListRet: []storage.Keypair{ + { + Key: "test/demo1-f1", + Value: `{"Field1":"demo1-f1", "Field2":"demo1-f2"}`, + }, + { + Key: "test/demo2-f1", + Value: `{"Field1":"demo2-f1", "Field2":"demo2-f2"}`, + }, }, giveWatchCh: make(chan storage.WatchResponse), giveResp: storage.WatchResponse{ @@ -154,12 +160,14 @@ func TestGenericStore_Init(t *testing.T) { }, wantCache: map[string]interface{}{ "demo2-f1": &TestStruct{ - Field1: "demo2-f1", - Field2: "demo2-f2", + BaseInfo: entity.BaseInfo{ID: "demo2-f1"}, + Field1: "demo2-f1", + Field2: "demo2-f2", }, "demo3-f1": &TestStruct{ - Field1: "demo3-f1", - Field2: "demo3-f2", + BaseInfo: entity.BaseInfo{ID: "demo3-f1"}, + Field1: "demo3-f1", + Field2: "demo3-f2", }, }, wantListCalled: true, @@ -183,9 +191,15 @@ func TestGenericStore_Init(t *testing.T) { }, }, }, - giveListRet: []string{ - `{"Field1","demo1-f1", "Field2":"demo1-f2"}`, - `{"Field1":"demo2-f1", "Field2":"demo2-f2"}`, + giveListRet: []storage.Keypair{ + { + Key: "test/demo1-f1", + Value: `{"Field1","demo1-f1", "Field2":"demo1-f2"}`, + }, + { + Key: "test/demo2-f1", + Value: `{"Field1":"demo2-f1", "Field2":"demo2-f2"}`, + }, }, wantErr: fmt.Errorf("json unmarshal failed: invalid character ',' after object key"), wantListCalled: true, @@ -765,3 +779,20 @@ func TestGenericStore_Delete(t *testing.T) { assert.Equal(t, tc.wantErr, err, tc.caseDesc) } } + +func TestGenericStore_StringToObjPtr(t *testing.T) { + s, err := NewGenericStore(GenericStoreOption{ + BasePath: "test", + ObjType: reflect.TypeOf(entity.SSL{}), + KeyFunc: func(obj interface{}) string { + r := obj.(*entity.Route) + return utils.InterfaceToString(r.ID) + }, + }) + assert.Nil(t, err) + id := "1" + sslStr := `{"key":"test_key", "cert":"test_cert"}` + sslInterface, err := s.StringToObjPtr(sslStr, id) + ssl := sslInterface.(*entity.SSL) + assert.Equal(t, id, ssl.ID) +} diff --git a/api/internal/core/store/storehub.go b/api/internal/core/store/storehub.go index e9c54ce1e1..fe6195352d 100644 --- a/api/internal/core/store/storehub.go +++ b/api/internal/core/store/storehub.go @@ -21,8 +21,8 @@ import ( "reflect" "github.com/apisix/manager-api/internal/core/entity" + "github.com/apisix/manager-api/internal/log" "github.com/apisix/manager-api/internal/utils" - "github.com/apisix/manager-api/log" ) type HubKey string diff --git a/api/internal/core/store/validate.go b/api/internal/core/store/validate.go index 7e3d0c195d..493c1698ab 100644 --- a/api/internal/core/store/validate.go +++ b/api/internal/core/store/validate.go @@ -25,9 +25,9 @@ import ( "github.com/xeipuuv/gojsonschema" "go.uber.org/zap/buffer" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" - "github.com/apisix/manager-api/log" + "github.com/apisix/manager-api/internal/log" ) type Validator interface { @@ -123,7 +123,7 @@ func cHashKeySchemaCheck(upstream *entity.UpstreamDef) error { if upstream.HashOn == "vars" { schemaDef = conf.Schema.Get("main.upstream_hash_vars_schema").String() if schemaDef == "" { - return fmt.Errorf("schema validate failed: schema not found, patch: main.upstream_hash_vars_schema") + return fmt.Errorf("schema validate failed: schema not found, path: main.upstream_hash_vars_schema") } } diff --git a/api/internal/core/store/validate_mock.go b/api/internal/core/store/validate_mock.go index 643ba78957..ad6922cfbb 100644 --- a/api/internal/core/store/validate_mock.go +++ b/api/internal/core/store/validate_mock.go @@ -1,5 +1,19 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. - +/* + * 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 mock "github.com/stretchr/testify/mock" @@ -13,12 +27,9 @@ type MockValidator struct { func (_m *MockValidator) Validate(obj interface{}) error { ret := _m.Called(obj) - var r0 error if rf, ok := ret.Get(0).(func(interface{}) error); ok { - r0 = rf(obj) - } else { - r0 = ret.Error(0) + return rf(obj) } - return r0 + return ret.Error(0) } diff --git a/api/internal/core/store/validate_test.go b/api/internal/core/store/validate_test.go index b50586d258..0bc549b7b7 100644 --- a/api/internal/core/store/validate_test.go +++ b/api/internal/core/store/validate_test.go @@ -305,7 +305,7 @@ func TestAPISIXJsonSchemaValidator_Plugin(t *testing.T) { err = json.Unmarshal([]byte(reqBody), route) assert.Nil(t, err) err = validator.Validate(route) - assert.Equal(t, fmt.Errorf("schema validate failed: (root): Must validate one and only one schema (oneOf)\n(root): Additional property disable is not allowed"), err) + assert.Equal(t, fmt.Errorf("schema validate failed: (root): Must validate one and only one schema (oneOf)\n(root): Additional property disable is not allowed\ndisable: Invalid type. Expected: boolean, given: integer"), err) } func TestAPISIXJsonSchemaValidator_Route_checkRemoteAddr(t *testing.T) { diff --git a/api/filter/authentication.go b/api/internal/filter/authentication.go similarity index 96% rename from api/filter/authentication.go rename to api/internal/filter/authentication.go index fd7c703434..142015f22e 100644 --- a/api/filter/authentication.go +++ b/api/internal/filter/authentication.go @@ -22,9 +22,8 @@ import ( "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" - - "github.com/apisix/manager-api/conf" - "github.com/apisix/manager-api/log" + "github.com/apisix/manager-api/internal/conf" + "github.com/apisix/manager-api/internal/log" ) func Authentication() gin.HandlerFunc { diff --git a/api/filter/cors.go b/api/internal/filter/cors.go similarity index 100% rename from api/filter/cors.go rename to api/internal/filter/cors.go diff --git a/api/filter/logging.go b/api/internal/filter/logging.go similarity index 100% rename from api/filter/logging.go rename to api/internal/filter/logging.go diff --git a/api/filter/logging_test.go b/api/internal/filter/logging_test.go similarity index 96% rename from api/filter/logging_test.go rename to api/internal/filter/logging_test.go index 688befa525..37c4cd3230 100644 --- a/api/filter/logging_test.go +++ b/api/internal/filter/logging_test.go @@ -24,7 +24,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" - "github.com/apisix/manager-api/log" + "github.com/apisix/manager-api/internal/log" ) func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder { diff --git a/api/filter/recover.go b/api/internal/filter/recover.go similarity index 98% rename from api/filter/recover.go rename to api/internal/filter/recover.go index 77e44a3311..9228e57d8c 100644 --- a/api/filter/recover.go +++ b/api/internal/filter/recover.go @@ -24,8 +24,8 @@ import ( "runtime" "time" - "github.com/apisix/manager-api/log" "github.com/gin-gonic/gin" + "github.com/apisix/manager-api/internal/log" ) var ( diff --git a/api/filter/request_id.go b/api/internal/filter/request_id.go similarity index 100% rename from api/filter/request_id.go rename to api/internal/filter/request_id.go diff --git a/api/filter/schema.go b/api/internal/filter/schema.go similarity index 93% rename from api/filter/schema.go rename to api/internal/filter/schema.go index 64ba821b9b..a2a99ee124 100644 --- a/api/filter/schema.go +++ b/api/internal/filter/schema.go @@ -32,8 +32,8 @@ import ( "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/store" + "github.com/apisix/manager-api/internal/log" "github.com/apisix/manager-api/internal/utils/consts" - "github.com/apisix/manager-api/log" ) var resources = map[string]string{ @@ -106,6 +106,18 @@ func parseCert(crt, key string) ([]string, error) { } func handleSpecialField(resource string, reqBody []byte) ([]byte, error) { + var bodyMap map[string]interface{} + err := json.Unmarshal(reqBody, &bodyMap) + if err != nil { + return reqBody, fmt.Errorf("read request body failed: %s", err) + } + if _, ok := bodyMap["create_time"]; ok { + return reqBody, errors.New("we don't accept create_time from client") + } + if _, ok := bodyMap["update_time"]; ok { + return reqBody, errors.New("we don't accept update_time from client") + } + // remove script, because it's a map, and need to be parsed into lua code if resource == "routes" { var route map[string]interface{} diff --git a/api/internal/handler/authentication/authentication.go b/api/internal/handler/authentication/authentication.go index c6acb421f4..523277fd83 100644 --- a/api/internal/handler/authentication/authentication.go +++ b/api/internal/handler/authentication/authentication.go @@ -27,7 +27,7 @@ import ( "github.com/shiningrush/droplet/wrapper" wgin "github.com/shiningrush/droplet/wrapper/gin" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/handler" ) diff --git a/api/internal/handler/consumer/consumer.go b/api/internal/handler/consumer/consumer.go index 31b7af37f2..b3ea5a14be 100644 --- a/api/internal/handler/consumer/consumer.go +++ b/api/internal/handler/consumer/consumer.go @@ -17,17 +17,21 @@ package consumer import ( + "fmt" + "net/http" "reflect" "strings" "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" ) type Handler struct { @@ -45,12 +49,10 @@ func (h *Handler) ApplyRoute(r *gin.Engine) { 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/:username", wgin.Wraps(h.Update, - wrapper.InputType(reflect.TypeOf(UpdateInput{})))) - r.PUT("/apisix/admin/consumers", wgin.Wraps(h.Update, - wrapper.InputType(reflect.TypeOf(UpdateInput{})))) + r.PUT("/apisix/admin/consumers/:username", wgin.Wraps(h.Set, + wrapper.InputType(reflect.TypeOf(SetInput{})))) + r.PUT("/apisix/admin/consumers", wgin.Wraps(h.Set, + wrapper.InputType(reflect.TypeOf(SetInput{})))) r.DELETE("/apisix/admin/consumers/:usernames", wgin.Wraps(h.BatchDelete, wrapper.InputType(reflect.TypeOf(BatchDeleteInput{})))) } @@ -128,25 +130,17 @@ func (h *Handler) List(c droplet.Context) (interface{}, error) { return ret, nil } -func (h *Handler) Create(c droplet.Context) (interface{}, error) { - input := c.Input().(*entity.Consumer) - input.ID = input.Username - - ensurePluginsDefValue(input.Plugins) - if err := h.consumerStore.Create(c.Context(), input); err != nil { - return handler.SpecCodeResponse(err), err - } - - return nil, nil -} - -type UpdateInput struct { - Username string `auto_read:"username,path"` +type SetInput struct { entity.Consumer + Username string `auto_read:"username,path"` } -func (h *Handler) Update(c droplet.Context) (interface{}, error) { - input := c.Input().(*UpdateInput) +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}, + fmt.Errorf("consumer's id and username must be a same value") + } if input.Username != "" { input.Consumer.Username = input.Username } diff --git a/api/internal/handler/consumer/consumer_test.go b/api/internal/handler/consumer/consumer_test.go index 6a8215453a..5c80d90b36 100644 --- a/api/internal/handler/consumer/consumer_test.go +++ b/api/internal/handler/consumer/consumer_test.go @@ -20,14 +20,16 @@ package consumer import ( "context" "fmt" - "github.com/apisix/manager-api/internal/core/entity" - "github.com/apisix/manager-api/internal/core/store" + "net/http" + "testing" + "github.com/shiningrush/droplet" "github.com/shiningrush/droplet/data" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "net/http" - "testing" + + "github.com/apisix/manager-api/internal/core/entity" + "github.com/apisix/manager-api/internal/core/store" ) func TestHandler_Get(t *testing.T) { @@ -172,31 +174,35 @@ func TestHandler_List(t *testing.T) { func TestHandler_Create(t *testing.T) { tests := []struct { caseDesc string - giveInput *entity.Consumer + giveInput *SetInput giveCtx context.Context giveErr error wantErr error - wantInput *entity.Consumer + wantInput *SetInput wantRet interface{} wantCalled bool }{ { caseDesc: "normal", - giveInput: &entity.Consumer{ - Username: "name", - Plugins: map[string]interface{}{ - "jwt-auth": map[string]interface{}{}, + giveInput: &SetInput{ + Consumer: entity.Consumer{ + Username: "name", + Plugins: map[string]interface{}{ + "jwt-auth": map[string]interface{}{}, + }, }, }, giveCtx: context.WithValue(context.Background(), "test", "value"), - wantInput: &entity.Consumer{ - BaseInfo: entity.BaseInfo{ - ID: "name", - }, - Username: "name", - Plugins: map[string]interface{}{ - "jwt-auth": map[string]interface{}{ - "exp": 86400, + wantInput: &SetInput{ + Consumer: entity.Consumer{ + BaseInfo: entity.BaseInfo{ + ID: "name", + }, + Username: "name", + Plugins: map[string]interface{}{ + "jwt-auth": map[string]interface{}{ + "exp": 86400, + }, }, }, }, @@ -205,23 +211,27 @@ func TestHandler_Create(t *testing.T) { }, { caseDesc: "store create failed", - giveInput: &entity.Consumer{ - Username: "name", - Plugins: map[string]interface{}{ - "jwt-auth": map[string]interface{}{ - "exp": 5000, + giveInput: &SetInput{ + Consumer: entity.Consumer{ + Username: "name", + Plugins: map[string]interface{}{ + "jwt-auth": map[string]interface{}{ + "exp": 5000, + }, }, }, }, giveErr: fmt.Errorf("create failed"), - wantInput: &entity.Consumer{ - BaseInfo: entity.BaseInfo{ - ID: "name", - }, - Username: "name", - Plugins: map[string]interface{}{ - "jwt-auth": map[string]interface{}{ - "exp": 5000, + wantInput: &SetInput{ + Consumer: entity.Consumer{ + BaseInfo: entity.BaseInfo{ + ID: "name", + }, + Username: "name", + Plugins: map[string]interface{}{ + "jwt-auth": map[string]interface{}{ + "exp": 5000, + }, }, }, }, @@ -237,17 +247,18 @@ func TestHandler_Create(t *testing.T) { t.Run(tc.caseDesc, func(t *testing.T) { methodCalled := true mStore := &store.MockInterface{} - mStore.On("Create", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + 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.Equal(t, &tc.wantInput.Consumer, args.Get(1)) + assert.True(t, args.Bool(2)) }).Return(tc.giveErr) h := Handler{consumerStore: mStore} ctx := droplet.NewContext() ctx.SetInput(tc.giveInput) ctx.SetContext(tc.giveCtx) - ret, err := h.Create(ctx) + ret, err := h.Set(ctx) assert.Equal(t, tc.wantCalled, methodCalled) assert.Equal(t, tc.wantRet, ret) assert.Equal(t, tc.wantErr, err) @@ -258,7 +269,7 @@ func TestHandler_Create(t *testing.T) { func TestHandler_Update(t *testing.T) { tests := []struct { caseDesc string - giveInput *UpdateInput + giveInput *SetInput giveCtx context.Context giveErr error wantErr error @@ -268,7 +279,7 @@ func TestHandler_Update(t *testing.T) { }{ { caseDesc: "normal", - giveInput: &UpdateInput{ + giveInput: &SetInput{ Username: "name", Consumer: entity.Consumer{ Plugins: map[string]interface{}{ @@ -295,7 +306,7 @@ func TestHandler_Update(t *testing.T) { }, { caseDesc: "store update failed", - giveInput: &UpdateInput{ + giveInput: &SetInput{ Username: "name", Consumer: entity.Consumer{ Plugins: map[string]interface{}{ @@ -338,7 +349,7 @@ func TestHandler_Update(t *testing.T) { ctx := droplet.NewContext() ctx.SetInput(tc.giveInput) ctx.SetContext(tc.giveCtx) - ret, err := h.Update(ctx) + ret, err := h.Set(ctx) assert.Equal(t, tc.wantCalled, methodCalled) assert.Equal(t, tc.wantRet, ret) assert.Equal(t, tc.wantErr, err) diff --git a/api/internal/handler/handler.go b/api/internal/handler/handler.go index 39256d9f9c..fecd0d3596 100644 --- a/api/internal/handler/handler.go +++ b/api/internal/handler/handler.go @@ -35,13 +35,16 @@ package handler import ( - "github.com/shiningrush/droplet" - "github.com/shiningrush/droplet/middleware" + "fmt" "net/http" "strings" "github.com/gin-gonic/gin" + "github.com/shiningrush/droplet" "github.com/shiningrush/droplet/data" + "github.com/shiningrush/droplet/middleware" + + "github.com/apisix/manager-api/internal/utils" ) type RegisterFactory func() (RouteRegister, error) @@ -87,3 +90,17 @@ func (mw *ErrorTransformMiddleware) Handle(ctx droplet.Context) error { } return nil } + +func IDCompare(idOnPath string, idOnBody interface{}) error { + idOnBodyStr, ok := idOnBody.(string) + if !ok { + idOnBodyStr = utils.InterfaceToString(idOnBody) + } + + // check if id on path is == to id on body ONLY if both ids are valid + if idOnPath != "" && idOnBodyStr != "" && idOnBodyStr != idOnPath { + return fmt.Errorf("ID on path (%s) doesn't match ID on body (%s)", idOnPath, idOnBodyStr) + } + + return nil +} diff --git a/api/internal/handler/handler_test.go b/api/internal/handler/handler_test.go new file mode 100644 index 0000000000..7fd288c041 --- /dev/null +++ b/api/internal/handler/handler_test.go @@ -0,0 +1,86 @@ +/* + * 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 handler + +import ( + "errors" + "net/http" + "testing" + + "github.com/go-playground/assert/v2" + "github.com/shiningrush/droplet/data" +) + +func TestSpecCodeResponse(t *testing.T) { + err := errors.New("schema validate failed: remote_addr: Must validate at least one schema (anyOf)") + resp := SpecCodeResponse(err) + assert.Equal(t, &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, resp) + + err = errors.New("data not found") + resp = SpecCodeResponse(err) + assert.Equal(t, &data.SpecCodeResponse{StatusCode: http.StatusNotFound}, resp) + + err = errors.New("system error") + resp = SpecCodeResponse(err) + assert.Equal(t, &data.SpecCodeResponse{StatusCode: http.StatusInternalServerError}, resp) +} + +func TestIDCompare(t *testing.T) { + // init + cases := []struct { + idOnPath, desc string + idOnBody interface{} + wantError error + }{ + { + desc: "ID on body is int, and it could be considered the same as ID on path", + idOnPath: "1", + idOnBody: 1, + }, + { + desc: "ID on body is int, and it is different from ID on path", + idOnPath: "1", + idOnBody: 2, + wantError: errors.New("ID on path (1) doesn't match ID on body (2)"), + }, + { + desc: "ID on body is same as ID on path", + idOnPath: "1", + idOnBody: "1", + }, + { + desc: "ID on body is different from ID on path", + idOnPath: "a", + idOnBody: "b", + wantError: errors.New("ID on path (a) doesn't match ID on body (b)"), + }, + { + desc: "No ID on body", + idOnPath: "1", + }, + { + desc: "No ID on path", + idOnBody: 1, + }, + } + for _, c := range cases { + t.Run(c.desc, func(t *testing.T) { + err := IDCompare(c.idOnPath, c.idOnBody) + assert.Equal(t, c.wantError, err) + }) + } +} diff --git a/api/internal/handler/plugin/plugin.go b/api/internal/handler/plugin/plugin.go index 6f4665510a..5703ede3ae 100644 --- a/api/internal/handler/plugin/plugin.go +++ b/api/internal/handler/plugin/plugin.go @@ -24,7 +24,7 @@ import ( "github.com/shiningrush/droplet/wrapper" wgin "github.com/shiningrush/droplet/wrapper/gin" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/handler" ) @@ -36,7 +36,8 @@ func NewHandler() (handler.RouteRegister, error) { } func (h *Handler) ApplyRoute(r *gin.Engine) { - r.GET("/apisix/admin/plugins", wgin.Wraps(h.Plugins)) + r.GET("/apisix/admin/plugins", wgin.Wraps(h.Plugins, + wrapper.InputType(reflect.TypeOf(ListInput{})))) r.GET("/apisix/admin/schema/plugins/:name", wgin.Wraps(h.Schema, wrapper.InputType(reflect.TypeOf(GetInput{})))) } @@ -61,10 +62,30 @@ func (h *Handler) Schema(c droplet.Context) (interface{}, error) { return ret, nil } +type ListInput struct { + All bool `auto_read:"all,query"` +} + func (h *Handler) Plugins(c droplet.Context) (interface{}, error) { - list := conf.Schema.Get("plugins").Map() + input := c.Input().(*ListInput) + + plugins := conf.Schema.Get("plugins") + if input.All { + var res []map[string]interface{} + list := plugins.Value().(map[string]interface{}) + for name, conf := range list { + plugin := conf.(map[string]interface{}) + plugin["name"] = name + if _, ok := plugin["type"]; !ok { + plugin["type"] = "other" + } + res = append(res, plugin) + } + return res, nil + } var ret []string + list := plugins.Map() for pluginName := range list { if pluginName != "serverless-post-function" && pluginName != "serverless-pre-function" { ret = append(ret, pluginName) diff --git a/api/internal/handler/plugin/plugin_test.go b/api/internal/handler/plugin/plugin_test.go index 85ac9d9e80..58127ba326 100644 --- a/api/internal/handler/plugin/plugin_test.go +++ b/api/internal/handler/plugin/plugin_test.go @@ -30,25 +30,50 @@ func TestPlugin(t *testing.T) { handler := &Handler{} assert.NotNil(t, handler) - //plugin list + // plugin list(old api, return name only) + listInput := &ListInput{} ctx := droplet.NewContext() + ctx.SetInput(listInput) list, err := handler.Plugins(ctx) assert.Nil(t, err) assert.Contains(t, list.([]string), "limit-count") - //schema - input := &GetInput{} - reqBody := `{ - "name": "limit-count" - }` - err = json.Unmarshal([]byte(reqBody), input) + // plugin list(return all fields of plugin) + listInput = &ListInput{ + All: true, + } + ctx = droplet.NewContext() + ctx.SetInput(listInput) + list, err = handler.Plugins(ctx) assert.Nil(t, err) + plugins := list.([]map[string]interface{}) + var authPlugins []string + var basicAuthConsumerSchema string + for _, plugin := range plugins { + if plugin["type"] == "auth" { + authPlugins = append(authPlugins, plugin["name"].(string)) + } + if plugin["name"] == "basic-auth" { + consumerSchemaByte, err := json.Marshal(plugin["consumer_schema"]) + basicAuthConsumerSchema = string(consumerSchemaByte) + assert.Nil(t, err) + } + } + // plugin type + assert.ElementsMatch(t, []string{"basic-auth", "jwt-auth", "hmac-auth", "key-auth", "wolf-rbac"}, authPlugins) + // consumer schema + assert.Equal(t, `{"additionalProperties":false,"properties":{"password":{"type":"string"},"username":{"type":"string"}},"required":["password","username"],"title":"work with consumer object","type":"object"}`, basicAuthConsumerSchema) + + // schema + input := &GetInput{ + Name: "limit-count", + } ctx.SetInput(input) val, _ := handler.Schema(ctx) assert.NotNil(t, val) - //not exists - reqBody = `{ + // not exists + reqBody := `{ "name": "not-exists" }` err = json.Unmarshal([]byte(reqBody), input) @@ -79,7 +104,7 @@ func TestPlugin(t *testing.T) { reqBody = `{ "name": "limit-count", "schema_type": "consumer" - }` + }` json.Unmarshal([]byte(reqBody), input) ctx.SetInput(input) val, _ = handler.Schema(ctx) diff --git a/api/internal/handler/route/route.go b/api/internal/handler/route/route.go index 54b958300f..59dc6cea5a 100644 --- a/api/internal/handler/route/route.go +++ b/api/internal/handler/route/route.go @@ -29,16 +29,15 @@ import ( "github.com/shiningrush/droplet" "github.com/shiningrush/droplet/data" "github.com/shiningrush/droplet/wrapper" - wgin "github.com/shiningrush/droplet/wrapper/gin" "github.com/yuin/gopher-lua" - - "github.com/apisix/manager-api/conf" + wgin "github.com/shiningrush/droplet/wrapper/gin" + "github.com/apisix/manager-api/internal/conf" "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/log" "github.com/apisix/manager-api/internal/utils" "github.com/apisix/manager-api/internal/utils/consts" - "github.com/apisix/manager-api/log" ) type Handler struct { @@ -348,13 +347,15 @@ type UpdateInput struct { func (h *Handler) Update(c droplet.Context) (interface{}, error) { input := c.Input().(*UpdateInput) - if input.ID != "" { - input.Route.ID = input.ID + + // check if ID in body is equal ID in path + if err := handler.IDCompare(input.ID, input.Route.ID); err != nil { + return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err } - if input.Route.Host != "" && len(input.Route.Hosts) > 0 { - return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, - fmt.Errorf("only one of host or hosts is allowed") + // if has id in path, use it + if input.ID != "" { + input.Route.ID = input.ID } //check depend diff --git a/api/internal/handler/route/route_test.go b/api/internal/handler/route/route_test.go index 39214b9796..f84fc901f9 100644 --- a/api/internal/handler/route/route_test.go +++ b/api/internal/handler/route/route_test.go @@ -27,7 +27,7 @@ import ( "github.com/shiningrush/droplet/data" "github.com/stretchr/testify/assert" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/storage" "github.com/apisix/manager-api/internal/core/store" @@ -757,6 +757,86 @@ func TestRoute(t *testing.T) { //sleep time.Sleep(time.Duration(100) * time.Millisecond) + // check ID discrepancy on Update + + // Fail: test the string body id value != string route id value + errRoute := &UpdateInput{} + errRoute.ID = "2" + err = json.Unmarshal([]byte(reqBody), errRoute) + assert.Nil(t, err) + ctx.SetInput(errRoute) + ret, err = handler.Update(ctx) + assert.NotNil(t, err) + assert.EqualError(t, err, "ID on path (2) doesn't match ID on body (1)") + assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode) + + // Fail: tests the float body id value != string route id value + reqBodyErr := `{ + "id": 1, + "uri": "/index.html", + "upstream": { + "type": "roundrobin", + "nodes": [{ + "host": "www.a.com", + "port": 80, + "weight": 1 + }] + } + }` + errRoute = &UpdateInput{} + errRoute.ID = "2" + err = json.Unmarshal([]byte(reqBodyErr), errRoute) + assert.Nil(t, err) + ctx.SetInput(errRoute) + ret, err = handler.Update(ctx) + assert.NotNil(t, err) + assert.EqualError(t, err, "ID on path (2) doesn't match ID on body (1)") + assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode) + + // Success: tests the float body id value is == string route id value + reqBodyErr = `{ + "id": 10, + "uri": "/index.html", + "upstream": { + "type": "roundrobin", + "nodes": [{ + "host": "www.a.com", + "port": 80, + "weight": 1 + }] + } + }` + errRoute = &UpdateInput{} + errRoute.ID = "10" + err = json.Unmarshal([]byte(reqBodyErr), errRoute) + assert.Nil(t, err) + ctx.SetInput(errRoute) + ret, err = handler.Update(ctx) + assert.Nil(t, err) + + // Success: tests the Body ID can be nil + reqBodyErr = `{ + "uri": "/index.html", + "upstream": { + "type": "roundrobin", + "nodes": [{ + "host": "www.a.com", + "port": 80, + "weight": 1 + }] + } + }` + errRoute = &UpdateInput{} + errRoute.ID = "r1" + err = json.Unmarshal([]byte(reqBodyErr), errRoute) + assert.Nil(t, err) + ctx.SetInput(errRoute) + ret, err = handler.Update(ctx) + assert.Nil(t, err) + + //sleep + time.Sleep(time.Duration(100) * time.Millisecond) + //list listInput := &ListInput{} reqBody = `{"page_size": 1, "page": 1}` @@ -1066,7 +1146,6 @@ func TestRoute(t *testing.T) { ctx.SetInput(inputDel) _, err = handler.BatchDelete(ctx) assert.Nil(t, err) - } func Test_Route_With_Script(t *testing.T) { @@ -1211,4 +1290,13 @@ func Test_Route_With_Script(t *testing.T) { assert.Nil(t, err) assert.Equal(t, stored.ID, route.ID) assert.Nil(t, stored.Script) + + //delete test data + inputDel := &BatchDelete{} + reqBody = `{"ids": "1"}` + err = json.Unmarshal([]byte(reqBody), inputDel) + assert.Nil(t, err) + ctx.SetInput(inputDel) + _, err = handler.BatchDelete(ctx) + assert.Nil(t, err) } diff --git a/api/internal/handler/service/service.go b/api/internal/handler/service/service.go index 1adb0a493d..799e58a3c0 100644 --- a/api/internal/handler/service/service.go +++ b/api/internal/handler/service/service.go @@ -179,6 +179,12 @@ type UpdateInput struct { func (h *Handler) Update(c droplet.Context) (interface{}, error) { input := c.Input().(*UpdateInput) + + // check if ID in body is equal ID in path + if err := handler.IDCompare(input.ID, input.Service.ID); err != nil { + return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err + } + if input.ID != "" { input.Service.ID = input.ID } diff --git a/api/internal/handler/service/service_test.go b/api/internal/handler/service/service_test.go index 81a56fe370..d7be7b8c38 100644 --- a/api/internal/handler/service/service_test.go +++ b/api/internal/handler/service/service_test.go @@ -25,7 +25,7 @@ import ( "github.com/shiningrush/droplet" "github.com/stretchr/testify/assert" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/storage" "github.com/apisix/manager-api/internal/core/store" diff --git a/api/internal/handler/ssl/ssl.go b/api/internal/handler/ssl/ssl.go index 19009954f8..0c9a3f201d 100644 --- a/api/internal/handler/ssl/ssl.go +++ b/api/internal/handler/ssl/ssl.go @@ -33,7 +33,7 @@ import ( "github.com/shiningrush/droplet/wrapper" wgin "github.com/shiningrush/droplet/wrapper/gin" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/store" "github.com/apisix/manager-api/internal/handler" @@ -86,7 +86,11 @@ func (h *Handler) Get(c droplet.Context) (interface{}, error) { } //format respond - ssl := ret.(*entity.SSL) + ssl := &entity.SSL{} + err = utils.ObjectClone(ret, ssl) + if err != nil { + return handler.SpecCodeResponse(err), err + } ssl.Key = "" ssl.Keys = nil @@ -160,9 +164,9 @@ func (h *Handler) List(c droplet.Context) (interface{}, error) { //format respond var list []interface{} - var ssl *entity.SSL for _, item := range ret.Rows { - ssl = item.(*entity.SSL) + ssl := &entity.SSL{} + _ = utils.ObjectClone(item, ssl) ssl.Key = "" ssl.Keys = nil list = append(list, ssl) @@ -199,6 +203,12 @@ type UpdateInput struct { func (h *Handler) Update(c droplet.Context) (interface{}, error) { input := c.Input().(*UpdateInput) + + // check if ID in body is equal ID in path + if err := handler.IDCompare(input.ID, input.SSL.ID); err != nil { + return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err + } + ssl, err := ParseCert(input.Cert, input.Key) if err != nil { return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err diff --git a/api/internal/handler/ssl/ssl_test.go b/api/internal/handler/ssl/ssl_test.go index 4a52032825..057d7ed59e 100644 --- a/api/internal/handler/ssl/ssl_test.go +++ b/api/internal/handler/ssl/ssl_test.go @@ -25,7 +25,7 @@ import ( "github.com/shiningrush/droplet" "github.com/stretchr/testify/assert" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/storage" "github.com/apisix/manager-api/internal/core/store" diff --git a/api/internal/handler/upstream/upstream.go b/api/internal/handler/upstream/upstream.go index 672906e5b4..790fbf0d99 100644 --- a/api/internal/handler/upstream/upstream.go +++ b/api/internal/handler/upstream/upstream.go @@ -17,12 +17,14 @@ package upstream import ( + "net/http" "reflect" "strings" "github.com/api7/go-jsonpatch" "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" @@ -161,6 +163,12 @@ type UpdateInput struct { func (h *Handler) Update(c droplet.Context) (interface{}, error) { input := c.Input().(*UpdateInput) + + // check if ID in body is equal ID in path + if err := handler.IDCompare(input.ID, input.Upstream.ID); err != nil { + return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err + } + if input.ID != "" { input.Upstream.ID = input.ID } diff --git a/api/internal/handler/upstream/upstream_test.go b/api/internal/handler/upstream/upstream_test.go index 03f4fe019f..6216633ae5 100644 --- a/api/internal/handler/upstream/upstream_test.go +++ b/api/internal/handler/upstream/upstream_test.go @@ -25,7 +25,7 @@ import ( "github.com/shiningrush/droplet" "github.com/stretchr/testify/assert" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/core/entity" "github.com/apisix/manager-api/internal/core/storage" "github.com/apisix/manager-api/internal/core/store" @@ -115,7 +115,7 @@ func TestUpstream(t *testing.T) { upstream2 := &UpdateInput{} upstream2.ID = "1" reqBody = `{ - "id": "aaa", + "id": "1", "name": "upstream3", "description": "upstream upstream", "type": "roundrobin", diff --git a/api/log/log.go b/api/internal/log/log.go similarity index 100% rename from api/log/log.go rename to api/internal/log/log.go diff --git a/api/log/zap.go b/api/internal/log/zap.go similarity index 98% rename from api/log/zap.go rename to api/internal/log/zap.go index cd36b5323e..d0d672025d 100644 --- a/api/log/zap.go +++ b/api/internal/log/zap.go @@ -22,7 +22,7 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" - "github.com/apisix/manager-api/conf" + "github.com/apisix/manager-api/internal/conf" ) var logger *zap.SugaredLogger diff --git a/api/internal/route.go b/api/internal/route.go index 3e38ea1608..f36e819b5f 100644 --- a/api/internal/route.go +++ b/api/internal/route.go @@ -26,8 +26,8 @@ import ( "github.com/gin-contrib/static" "github.com/gin-gonic/gin" - "github.com/apisix/manager-api/conf" - "github.com/apisix/manager-api/filter" + "github.com/apisix/manager-api/internal/conf" + "github.com/apisix/manager-api/internal/filter" "github.com/apisix/manager-api/internal/handler" "github.com/apisix/manager-api/internal/handler/authentication" "github.com/apisix/manager-api/internal/handler/consumer" @@ -40,7 +40,7 @@ import ( "github.com/apisix/manager-api/internal/handler/service" "github.com/apisix/manager-api/internal/handler/ssl" "github.com/apisix/manager-api/internal/handler/upstream" - "github.com/apisix/manager-api/log" + "github.com/apisix/manager-api/internal/log" ) func SetUpRouter() *gin.Engine { diff --git a/api/internal/utils/consts/api_error.go b/api/internal/utils/consts/api_error.go index 608ad0ef05..4e2a0c0299 100644 --- a/api/internal/utils/consts/api_error.go +++ b/api/internal/utils/consts/api_error.go @@ -17,8 +17,10 @@ package consts import ( - "github.com/gin-gonic/gin" "net/http" + "strings" + + "github.com/gin-gonic/gin" ) type WrapperHandle func(c *gin.Context) (interface{}, error) @@ -27,7 +29,21 @@ func ErrorWrapper(handle WrapperHandle) gin.HandlerFunc { return func(c *gin.Context) { data, err := handle(c) if err != nil { - apiError := err.(*ApiError) + apiError, ok := err.(*ApiError) + if !ok { + errMsg := err.Error() + if strings.Contains(errMsg, "required") || + strings.Contains(errMsg, "conflicted") || + strings.Contains(errMsg, "invalid") || + strings.Contains(errMsg, "missing") || + strings.Contains(errMsg, "validate failed") { + apiError = InvalidParam(errMsg) + } else if strings.Contains(errMsg, "not found") { + apiError = NotFound(errMsg) + } else { + apiError = SystemError(errMsg) + } + } c.JSON(apiError.Status, apiError) return } @@ -53,5 +69,9 @@ func InvalidParam(message string) *ApiError { } func SystemError(message string) *ApiError { - return &ApiError{500, 500, message} + return &ApiError{500, 10001, message} +} + +func NotFound(message string) *ApiError { + return &ApiError{404, 10002, message} } diff --git a/api/internal/utils/consts/api_error_test.go b/api/internal/utils/consts/api_error_test.go new file mode 100644 index 0000000000..9be241e4ea --- /dev/null +++ b/api/internal/utils/consts/api_error_test.go @@ -0,0 +1,62 @@ +/* + * 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 consts + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" +) + +func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder { + req := httptest.NewRequest(method, path, nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + return w +} + +func TestRequestLogHandler(t *testing.T) { + r := gin.New() + r.GET("/", ErrorWrapper(func(c *gin.Context) (interface{}, error) { + return nil, nil + })) + r.GET("/notfound", ErrorWrapper(func(c *gin.Context) (interface{}, error) { + return nil, fmt.Errorf("data not found") + })) + r.GET("/invalid", ErrorWrapper(func(c *gin.Context) (interface{}, error) { + return nil, fmt.Errorf("schema validate failed") + })) + r.GET("/error", ErrorWrapper(func(c *gin.Context) (interface{}, error) { + return nil, fmt.Errorf("internal system error") + })) + + w := performRequest(r, "GET", "/") + assert.Equal(t, 200, w.Code) + + w = performRequest(r, "GET", "/notfound") + assert.Equal(t, 404, w.Code) + + w = performRequest(r, "GET", "/invalid") + assert.Equal(t, 400, w.Code) + + w = performRequest(r, "GET", "/error") + assert.Equal(t, 500, w.Code) +} diff --git a/api/internal/utils/utils.go b/api/internal/utils/utils.go index ad477925af..b8d192c70b 100644 --- a/api/internal/utils/utils.go +++ b/api/internal/utils/utils.go @@ -17,6 +17,7 @@ package utils import ( + "encoding/json" "errors" "fmt" "net" @@ -97,6 +98,17 @@ func InterfaceToString(val interface{}) string { return str } +// Note: json.Marshal and json.Unmarshal may cause the precision loss +func ObjectClone(origin, copy interface{}) error { + byt, err := json.Marshal(origin) + if err != nil { + return err + } + + err = json.Unmarshal(byt, copy) + return err +} + func GenLabelMap(label string) (map[string]string, error) { var err = errors.New("malformed label") mp := make(map[string]string) diff --git a/api/internal/utils/utils_test.go b/api/internal/utils/utils_test.go index 0d8427de61..8da295f83a 100644 --- a/api/internal/utils/utils_test.go +++ b/api/internal/utils/utils_test.go @@ -44,6 +44,24 @@ func TestSumIPs_with_nil(t *testing.T) { assert.Equal(t, uint16(0), total) } +func TestObjectClone(t *testing.T) { + type test struct { + Str string + Num int + } + + origin := &test{Str: "a", Num: 1} + copy := &test{} + err := ObjectClone(origin, copy) + assert.Nil(t, err) + assert.Equal(t, origin, copy) + + // change value of the copy, should not change value of origin + copy.Num = 2 + assert.NotEqual(t, copy.Num, origin.Num) + assert.Equal(t, 1, origin.Num) +} + func TestGenLabelMap(t *testing.T) { expectedErr := errors.New("malformed label") mp, err := GenLabelMap("l1") diff --git a/api/main.go b/api/main.go deleted file mode 100644 index 4e4eec176b..0000000000 --- a/api/main.go +++ /dev/null @@ -1,104 +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 main - -import ( - "context" - "fmt" - "net/http" - "os" - "os/signal" - "syscall" - "time" - - "github.com/shiningrush/droplet" - - "github.com/apisix/manager-api/conf" - "github.com/apisix/manager-api/internal" - "github.com/apisix/manager-api/internal/core/storage" - "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/log" -) - -var Version string - -func printInfo() { - fmt.Fprint(os.Stdout, "The manager-api is running successfully!\n\n") - fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Version", Version) - fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "Listen", conf.ServerHost, conf.ServerPort) - fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Loglevel", conf.ErrorLogLevel) - fmt.Fprintf(os.Stdout, "%-8s: %s\n\n", "Logfile", conf.ErrorLogPath) -} - -func main() { - droplet.Option.Orchestrator = func(mws []droplet.Middleware) []droplet.Middleware { - var newMws []droplet.Middleware - // default middleware order: resp_reshape, auto_input, traffic_log - // We should put err_transform at second to catch all error - newMws = append(newMws, mws[0], &handler.ErrorTransformMiddleware{}) - newMws = append(newMws, mws[1:]...) - return newMws - } - - if err := storage.InitETCDClient(conf.ETCDConfig); err != nil { - log.Errorf("init etcd client fail: %w", err) - panic(err) - } - if err := store.InitStores(); err != nil { - log.Errorf("init stores fail: %w", err) - panic(err) - } - // routes - r := internal.SetUpRouter() - addr := fmt.Sprintf("%s:%d", conf.ServerHost, conf.ServerPort) - s := &http.Server{ - Addr: addr, - Handler: r, - ReadTimeout: time.Duration(1000) * time.Millisecond, - WriteTimeout: time.Duration(5000) * time.Millisecond, - } - - log.Infof("The Manager API is listening on %s", addr) - - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) - - go func() { - if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { - utils.CloseAll() - log.Fatalf("listen and serv fail: %s", err) - } - }() - - printInfo() - - sig := <-quit - log.Infof("The Manager API server receive %s and start shutting down", sig.String()) - - ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) - defer cancel() - - if err := s.Shutdown(ctx); err != nil { - log.Errorf("Shutting down server error: %s", err) - } - - log.Infof("The Manager API server exited") - - utils.CloseAll() -} diff --git a/api/test/docker/Dockerfile b/api/test/docker/Dockerfile index ca96799215..216aa53f72 100644 --- a/api/test/docker/Dockerfile +++ b/api/test/docker/Dockerfile @@ -25,7 +25,7 @@ RUN mkdir -p /go/manager-api/conf \ && mkdir -p /go/manager-api/build-tools \ && go env -w GOPROXY=https://goproxy.io,direct \ && export GOPROXY=https://goproxy.io \ - && go build -o /go/manager-api/manager-api \ + && go build -o /go/manager-api/manager-api ./cmd/manager \ && mv /go/src/github.com/apisix/manager-api/entry.sh /go/manager-api/ \ && mv /go/src/github.com/apisix/manager-api/build-tools/* /go/manager-api/build-tools/ \ && mv /go/src/github.com/apisix/manager-api/conf/conf.yaml /go/manager-api/conf/conf.yaml \ diff --git a/api/test/e2e/balancer_test.go b/api/test/e2e/balancer_test.go index 868f301563..3e6d4d61b5 100644 --- a/api/test/e2e/balancer_test.go +++ b/api/test/e2e/balancer_test.go @@ -27,10 +27,10 @@ import ( func TestBalancer_roundrobin_with_weight(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create upstream (roundrobin with same weight)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create upstream (roundrobin with same weight)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -53,10 +53,10 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -68,7 +68,7 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -82,10 +82,10 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "create upstream (roundrobin with different weight)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create upstream (roundrobin with different weight)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -109,7 +109,7 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -123,10 +123,10 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "create upstream (roundrobin with weight 1 and 0) ", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create upstream (roundrobin with weight 1 and 0) ", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -145,7 +145,7 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -157,10 +157,10 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "create upstream (roundrobin with weight only 1 ) ", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create upstream (roundrobin with weight only 1 ) ", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -174,7 +174,7 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -188,7 +188,7 @@ func TestBalancer_roundrobin_with_weight(t *testing.T) { func TestBalancer_Delete(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/1", @@ -196,7 +196,7 @@ func TestBalancer_Delete(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete upstream", + Desc: "delete upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/1", @@ -204,7 +204,7 @@ func TestBalancer_Delete(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -215,6 +215,6 @@ func TestBalancer_Delete(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/base.go b/api/test/e2e/base.go index ad293ae6b7..5c79f857c1 100644 --- a/api/test/e2e/base.go +++ b/api/test/e2e/base.go @@ -20,7 +20,7 @@ import ( "bytes" "context" "crypto/tls" - "github.com/stretchr/testify/assert" + "io/ioutil" "net" "net/http" @@ -28,11 +28,16 @@ import ( "time" "github.com/gavv/httpexpect/v2" + "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" ) var token string + +var APISIXHost = "http://127.0.0.1:9080" var APISIXInternalUrl = "http://172.16.238.30:9080" +var APISIXSingleWorkerHost = "http://127.0.0.1:9081" +var ManagerAPIHost = "http://127.0.0.1:9000" func init() { //login to get auth token @@ -41,7 +46,7 @@ func init() { "password": "admin" }`) - url := "http://127.0.0.1:9000/apisix/admin/user/login" + url := ManagerAPIHost + "/apisix/admin/user/login" req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(requestBody)) if err != nil { panic(err) @@ -86,11 +91,11 @@ func httpGet(url string) ([]byte, int, error) { } func ManagerApiExpect(t *testing.T) *httpexpect.Expect { - return httpexpect.New(t, "http://127.0.0.1:9000") + return httpexpect.New(t, ManagerAPIHost) } func APISIXExpect(t *testing.T) *httpexpect.Expect { - return httpexpect.New(t, "http://127.0.0.1:9080") + return httpexpect.New(t, APISIXHost) } func APISIXHTTPSExpect(t *testing.T) *httpexpect.Expect { @@ -117,10 +122,8 @@ func APISIXHTTPSExpect(t *testing.T) *httpexpect.Expect { return e } -var singleWorkerAPISIXHost = "http://127.0.0.1:9081" - func BatchTestServerPort(t *testing.T, times int) map[string]int { - url := singleWorkerAPISIXHost + "/server_port" + url := APISIXSingleWorkerHost + "/server_port" req, err := http.NewRequest(http.MethodGet, url, nil) assert.Nil(t, err) @@ -154,7 +157,7 @@ func BatchTestServerPort(t *testing.T, times int) map[string]int { var sleepTime = time.Duration(300) * time.Millisecond type HttpTestCase struct { - caseDesc string + Desc string Object *httpexpect.Expect Method string Path string @@ -170,66 +173,70 @@ type HttpTestCase struct { Sleep time.Duration //ms } -func testCaseCheck(tc HttpTestCase) { - //init - expectObj := tc.Object - var req *httpexpect.Request - switch tc.Method { - case http.MethodGet: - req = expectObj.GET(tc.Path) - case http.MethodPut: - req = expectObj.PUT(tc.Path) - case http.MethodPost: - req = expectObj.POST(tc.Path) - case http.MethodDelete: - req = expectObj.DELETE(tc.Path) - case http.MethodPatch: - req = expectObj.PATCH(tc.Path) - case http.MethodOptions: - req = expectObj.OPTIONS(tc.Path) - default: - } +func testCaseCheck(tc HttpTestCase, t *testing.T) { + t.Run(tc.Desc, func(t *testing.T) { + //init + expectObj := tc.Object + var req *httpexpect.Request + switch tc.Method { + case http.MethodGet: + req = expectObj.GET(tc.Path) + case http.MethodPut: + req = expectObj.PUT(tc.Path) + case http.MethodPost: + req = expectObj.POST(tc.Path) + case http.MethodDelete: + req = expectObj.DELETE(tc.Path) + case http.MethodPatch: + req = expectObj.PATCH(tc.Path) + case http.MethodOptions: + req = expectObj.OPTIONS(tc.Path) + default: + } - if req == nil { - panic("fail to init request") - } + if req == nil { + panic("fail to init request") + } - if tc.Sleep != 0 { - time.Sleep(tc.Sleep) - } + if tc.Sleep != 0 { + time.Sleep(tc.Sleep) + } else { + time.Sleep(time.Duration(50) * time.Millisecond) + } - if tc.Query != "" { - req.WithQueryString(tc.Query) - } + if tc.Query != "" { + req.WithQueryString(tc.Query) + } - //set header - for key, val := range tc.Headers { - req.WithHeader(key, val) - } + //set header + for key, val := range tc.Headers { + req.WithHeader(key, val) + } - //set body - if tc.Body != "" { - req.WithText(tc.Body) - } + //set body + if tc.Body != "" { + req.WithText(tc.Body) + } - //respond check - resp := req.Expect() + //respond check + resp := req.Expect() - //match http status - if tc.ExpectStatus != 0 { - resp.Status(tc.ExpectStatus) - } + //match http status + if tc.ExpectStatus != 0 { + resp.Status(tc.ExpectStatus) + } - //match headers - if tc.ExpectHeaders != nil { - for key, val := range tc.ExpectHeaders { - resp.Header(key).Equal(val) + //match headers + if tc.ExpectHeaders != nil { + for key, val := range tc.ExpectHeaders { + resp.Header(key).Equal(val) + } } - } - //match body - if tc.ExpectBody != "" { - resp.Body().Contains(tc.ExpectBody) - } + //match body + if tc.ExpectBody != "" { + resp.Body().Contains(tc.ExpectBody) + } + }) } diff --git a/api/test/e2e/consumer_test.go b/api/test/e2e/consumer_test.go index e7ba2316b5..6c26170ec8 100644 --- a/api/test/e2e/consumer_test.go +++ b/api/test/e2e/consumer_test.go @@ -27,13 +27,191 @@ import ( "github.com/tidwall/gjson" ) +func TestConsumer_Create_And_Get(t *testing.T) { + tests := []HttpTestCase{ + { + Desc: "check consumer is not exist", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_1", + Method: http.MethodGet, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusNotFound, + ExpectBody: "data not found", + }, + { + Desc: "check consumer is not exist", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_2", + Method: http.MethodGet, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusNotFound, + ExpectBody: "data not found", + }, + { + Desc: "create consumer by POST method", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPost, + Body: `{ + "username": "consumer_1", + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + } + }, + "desc": "test description" + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusNotFound, + ExpectBody: "404 page not found", + }, + { + Desc: "create consumer by PUT method", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, + Body: `{ + "username": "consumer_2", + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + } + }, + "desc": "test description" + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"code\":0", + }, + { + Desc: "get consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_2", + Method: http.MethodGet, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"username\":\"consumer_2\"", + Sleep: sleepTime, + }, + { + Desc: "create consumer without username", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, + Body: `{ + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + } + }, + "desc": "test description" + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + ExpectBody: "\"code\":10000", + }, + { + Desc: "delete consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_2", + Method: http.MethodDelete, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"code\":0", + }, + } + + for _, tc := range tests { + testCaseCheck(tc, t) + } +} + +func TestConsumer_Update_And_Get(t *testing.T) { + tests := []HttpTestCase{ + { + Desc: "create consumer by PUT", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, + Body: `{ + "username": "consumer_3", + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + } + }, + "desc": "test description" + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"code\":0", + }, + { + Desc: "update consumer by PUT", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_3", + Method: http.MethodPut, + Body: `{ + "username": "consumer_3", + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 504, + "key": "remote_addr" + } + }, + "desc": "test description" + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"code\":0", + }, + { + Desc: "get consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_3", + Method: http.MethodGet, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"rejected_code\":504", + Sleep: sleepTime, + }, + { + Desc: "delete consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/consumer_3", + Method: http.MethodDelete, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: "\"code\":0", + }, + } + + for _, tc := range tests { + testCaseCheck(tc, t) + } +} + func TestConsumer_with_key_auth(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -52,7 +230,7 @@ func TestConsumer_with_key_auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit route without apikey", + Desc: "hit route without apikey", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -61,10 +239,10 @@ func TestConsumer_with_key_auth(t *testing.T) { Sleep: sleepTime * 2, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -78,7 +256,7 @@ func TestConsumer_with_key_auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit route with correct apikey", + Desc: "hit route with correct apikey", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -88,7 +266,7 @@ func TestConsumer_with_key_auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit route with incorrect apikey", + Desc: "hit route with incorrect apikey", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -98,7 +276,7 @@ func TestConsumer_with_key_auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -106,7 +284,7 @@ func TestConsumer_with_key_auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete consumer (as delete not exist consumer)", + Desc: "delete consumer (as delete not exist consumer)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -114,7 +292,7 @@ func TestConsumer_with_key_auth(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "hit route (consumer deleted)", + Desc: "hit route (consumer deleted)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -124,7 +302,7 @@ func TestConsumer_with_key_auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -134,17 +312,17 @@ func TestConsumer_with_key_auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestConsumer_with_notexist_plugin(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create consumer with not exist plugin", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer with not exist plugin", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -159,7 +337,7 @@ func TestConsumer_with_notexist_plugin(t *testing.T) { ExpectBody: "schema validate failed: schema not found, path: plugins.key-authaa", }, { - caseDesc: "verify the consumer", + Desc: "verify the consumer", Object: ManagerApiExpect(t), Path: "/apisix/admin/consumers/jack", Method: http.MethodGet, @@ -170,17 +348,17 @@ func TestConsumer_with_notexist_plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestConsumer_add_consumer_with_labels(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create the consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create the consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "labels": { @@ -199,7 +377,7 @@ func TestConsumer_add_consumer_with_labels(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the consumer", + Desc: "verify the consumer", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -209,10 +387,10 @@ func TestConsumer_add_consumer_with_labels(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create the route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create the route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -231,7 +409,7 @@ func TestConsumer_add_consumer_with_labels(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route with correct apikey", + Desc: "hit the route with correct apikey", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -240,7 +418,7 @@ func TestConsumer_add_consumer_with_labels(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the consumer", + Desc: "delete the consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -248,7 +426,7 @@ func TestConsumer_add_consumer_with_labels(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete the route", + Desc: "delete the route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -258,17 +436,17 @@ func TestConsumer_add_consumer_with_labels(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestConsumer_with_createtime_updatetime(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create the consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create the consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username":"jack", "desc": "new consumer" @@ -279,7 +457,7 @@ func TestConsumer_with_createtime_updatetime(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } basepath := "http://127.0.0.1:9000/apisix/admin/consumers" @@ -302,10 +480,10 @@ func TestConsumer_with_createtime_updatetime(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "update the consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "update the consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username":"jack", "desc": "updated consumer" @@ -317,7 +495,7 @@ func TestConsumer_with_createtime_updatetime(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // get the consumer @@ -336,7 +514,7 @@ func TestConsumer_with_createtime_updatetime(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "delete the consumer", + Desc: "delete the consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -344,7 +522,7 @@ func TestConsumer_with_createtime_updatetime(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "after delete consumer verify it again", + Desc: "after delete consumer verify it again", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -355,6 +533,6 @@ func TestConsumer_with_createtime_updatetime(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/id_compatible_test.go b/api/test/e2e/id_compatible_test.go index ea53c4bd82..33dc865229 100644 --- a/api/test/e2e/id_compatible_test.go +++ b/api/test/e2e/id_compatible_test.go @@ -17,34 +17,39 @@ package e2e import ( + "io/ioutil" "net/http" "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/tidwall/gjson" ) func TestID_Using_Int(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create upstream", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams", + Desc: "create upstream", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams", Body: `{ - "id": 1, - "nodes": [{ - "host": "172.16.238.20", - "port": 1980, - "weight": 1 - }], - "type": "roundrobin" + "id": 1, + "nodes": [{ + "host": "172.16.238.20", + "port": 1980, + "weight": 1 + }], + "type": "roundrobin" }`, Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/hello", "upstream_id": 1 @@ -54,7 +59,7 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just created", + Desc: "hit the route just created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -63,10 +68,10 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create service", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/services", + Desc: "create service", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/services", Body: `{ "id": 1, "upstream_id": 1 @@ -75,10 +80,10 @@ func TestID_Using_Int(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "update route to use the service just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "update route to use the service just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/hello", "service_id": 1 @@ -88,7 +93,7 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just updated", + Desc: "hit the route just updated", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -97,7 +102,7 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route", + Desc: "delete the route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/1", @@ -105,7 +110,7 @@ func TestID_Using_Int(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete the service", + Desc: "delete the service", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/services/1", @@ -114,7 +119,7 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "make sure the service has been deleted", + Desc: "make sure the service has been deleted", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/services/1", @@ -123,7 +128,7 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the upstream", + Desc: "delete the upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/1", @@ -131,7 +136,7 @@ func TestID_Using_Int(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the upstream has been deleted", + Desc: "make sure the upstream has been deleted", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/upstreams/1", @@ -140,7 +145,7 @@ func TestID_Using_Int(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit deleted route", + Desc: "hit deleted route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -150,34 +155,34 @@ func TestID_Using_Int(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestID_Using_String(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create upstream", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams", + Desc: "create upstream", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams", Body: `{ - "id": "2", - "nodes": [{ - "host": "172.16.238.20", - "port": 1980, - "weight": 1 - }], - "type": "roundrobin" + "id": "2", + "nodes": [{ + "host": "172.16.238.20", + "port": 1980, + "weight": 1 + }], + "type": "roundrobin" }`, Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/2", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/2", Body: `{ "uri": "/hello", "upstream_id": "2" @@ -187,7 +192,7 @@ func TestID_Using_String(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just created", + Desc: "hit the route just created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -196,7 +201,7 @@ func TestID_Using_String(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route", + Desc: "delete the route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/2", @@ -204,15 +209,16 @@ func TestID_Using_String(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete the upstream", + Desc: "delete the upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/2", Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, + Sleep: sleepTime, }, { - caseDesc: "make sure the upstream has been deleted", + Desc: "make sure the upstream has been deleted", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/upstreams/2", @@ -221,7 +227,7 @@ func TestID_Using_String(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit deleted route", + Desc: "hit deleted route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -231,34 +237,34 @@ func TestID_Using_String(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestID_Crossing(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create upstream by admin api", - Object: APISIXExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams", + Desc: "create upstream by admin api", + Object: APISIXExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams", Body: `{ - "id": 3, - "nodes": [{ - "host": "172.16.238.20", - "port": 1980, - "weight": 1 - }], - "type": "roundrobin" + "id": 3, + "nodes": [{ + "host": "172.16.238.20", + "port": 1980, + "weight": 1 + }], + "type": "roundrobin" }`, Headers: map[string]string{"X-API-KEY": "edd1c9f034335f136f87ad84b625c8f1"}, ExpectStatus: http.StatusCreated, }, { - caseDesc: "create route by admin api", - Object: APISIXExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/3", + Desc: "create route by admin api", + Object: APISIXExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/3", Body: `{ "uri": "/hello", "upstream_id": 3 @@ -268,7 +274,7 @@ func TestID_Crossing(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify that the upstream is available for manager api", + Desc: "verify that the upstream is available for manager api", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/upstreams/3", @@ -278,7 +284,7 @@ func TestID_Crossing(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify that the route is available for manager api", + Desc: "verify that the route is available for manager api", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/routes/3", @@ -288,7 +294,7 @@ func TestID_Crossing(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just created", + Desc: "hit the route just created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -297,7 +303,7 @@ func TestID_Crossing(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route", + Desc: "delete the route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/3", @@ -305,15 +311,16 @@ func TestID_Crossing(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete the upstream", + Desc: "delete the upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/3", Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, + Sleep: sleepTime, }, { - caseDesc: "make sure the upstream has been deleted", + Desc: "make sure the upstream has been deleted", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/upstreams/3", @@ -322,7 +329,7 @@ func TestID_Crossing(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit deleted route", + Desc: "hit deleted route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -332,6 +339,135 @@ func TestID_Crossing(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) + } +} + +func TestID_Not_In_Body(t *testing.T) { + tests := []HttpTestCase{ + { + Desc: "make sure the route is not created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusNotFound, + Sleep: sleepTime, + }, + { + Desc: "create route that has no ID in request body by admin api", + Object: APISIXExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", + Body: `{ + "uri": "/hello", + "upstream": { + "type": "roundrobin", + "nodes": { + "172.16.238.20:1980": 1 + } + } + }`, + Headers: map[string]string{"X-API-KEY": "edd1c9f034335f136f87ad84b625c8f1"}, + ExpectStatus: http.StatusCreated, + Sleep: sleepTime, + }, + { + Desc: "verify that the route is available for manager api", + Object: ManagerApiExpect(t), + Method: http.MethodGet, + Path: "/apisix/admin/routes/r1", + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: `"id":"r1"`, + Sleep: sleepTime, + }, + { + Desc: "hit the route just created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusOK, + ExpectBody: "hello world", + Sleep: sleepTime, + }, + { + Desc: "delete the route", + Object: ManagerApiExpect(t), + Method: http.MethodDelete, + Path: "/apisix/admin/routes/r1", + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + }, + { + Desc: "hit deleted route", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusNotFound, + Sleep: sleepTime, + }, + { + Desc: "create route that has no ID in request body by admin api (POST)", + Object: APISIXExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/routes", + Body: `{ + "uri": "/hello", + "upstream": { + "type": "roundrobin", + "nodes": { + "172.16.238.20:1980": 1 + } + } + }`, + Headers: map[string]string{"X-API-KEY": "edd1c9f034335f136f87ad84b625c8f1"}, + ExpectStatus: http.StatusCreated, + Sleep: sleepTime, + }, + { + Desc: "verify that the route is available for manager api", + Object: ManagerApiExpect(t), + Method: http.MethodGet, + Path: "/apisix/admin/routes", + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + ExpectBody: `"uri":"/hello"`, + Sleep: sleepTime, + }, + { + Desc: "hit the route just created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusOK, + ExpectBody: "hello world", + Sleep: sleepTime, + }, + } + + for _, tc := range tests { + testCaseCheck(tc, t) + } + + // delete the route created by POST + time.Sleep(time.Duration(100) * time.Millisecond) + request, _ := http.NewRequest("GET", ManagerAPIHost+"/apisix/admin/routes", nil) + request.Header.Add("Authorization", token) + resp, err := http.DefaultClient.Do(request) + assert.Nil(t, err) + defer resp.Body.Close() + respBody, _ := ioutil.ReadAll(resp.Body) + list := gjson.Get(string(respBody), "data.rows").Value().([]interface{}) + for _, item := range list { + route := item.(map[string]interface{}) + tc := HttpTestCase{ + Desc: "delete the route", + Object: ManagerApiExpect(t), + Method: http.MethodDelete, + Path: "/apisix/admin/routes/" + route["id"].(string), + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + } + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/json_schema_validate_test.go b/api/test/e2e/json_schema_validate_test.go index a025b2ec82..1adcc11a6e 100644 --- a/api/test/e2e/json_schema_validate_test.go +++ b/api/test/e2e/json_schema_validate_test.go @@ -24,10 +24,10 @@ import ( func TestSchema_not_exist_field(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "config route with non-existent fields", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "config route with non-existent fields", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello", "nonexistent": "test non-existent", @@ -42,10 +42,10 @@ func TestSchema_not_exist_field(t *testing.T) { }`, Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusBadRequest, - ExpectBody: `{"code":10000,"message":"schema validate failed: (root): Additional property nonexistent is not allowed"}`, + ExpectBody: `{"code":10000,"message":"schema validate failed: (root): Additional property nonexistent is not allowed"}`, }, { - caseDesc: "make sure the route create failed", + Desc: "make sure the route create failed", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -55,6 +55,6 @@ func TestSchema_not_exist_field(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/label_test.go b/api/test/e2e/label_test.go index 4fe5713405..b984c086b8 100644 --- a/api/test/e2e/label_test.go +++ b/api/test/e2e/label_test.go @@ -25,10 +25,10 @@ func TestLabel(t *testing.T) { // Todo: test ssl after ssl bug fixed tests := []HttpTestCase{ { - caseDesc: "config route", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "config route", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello", "labels": { @@ -49,10 +49,10 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers/c1", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers/c1", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -71,10 +71,10 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create upstream", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/u1", + Desc: "create upstream", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/u1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -92,10 +92,10 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create service", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/services", + Desc: "create service", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/services", Body: `{ "id": "s1", "plugins": { @@ -125,16 +125,17 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "get route label", + Desc: "get route label", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, Path: "/apisix/admin/labels/route", ExpectStatus: http.StatusOK, ExpectBody: "{\"build\":\"16\"},{\"env\":\"production\"},{\"version\":\"v2\"}", + Sleep: sleepTime, }, { - caseDesc: "get consumer label", + Desc: "get consumer label", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -143,7 +144,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"16\"},{\"env\":\"production\"},{\"version\":\"v3\"}", }, { - caseDesc: "get upstream label", + Desc: "get upstream label", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -152,7 +153,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"17\"},{\"env\":\"production\"},{\"version\":\"v2\"}", }, { - caseDesc: "get service label", + Desc: "get service label", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -161,7 +162,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"16\"},{\"env\":\"production\"},{\"extra\":\"test\"},{\"version\":\"v2\"}", }, { - caseDesc: "get all label", + Desc: "get all label", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -170,7 +171,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"},{\"extra\":\"test\"},{\"version\":\"v2\"},{\"version\":\"v3\"}", }, { - caseDesc: "get label with page", + Desc: "get label with page", Object: ManagerApiExpect(t), Method: http.MethodGet, Query: "page=1&page_size=1", @@ -180,7 +181,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"16\"}", }, { - caseDesc: "get label with page", + Desc: "get label with page", Object: ManagerApiExpect(t), Method: http.MethodGet, Query: "page=3&page_size=1", @@ -190,7 +191,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"env\":\"production\"}", }, { - caseDesc: "get labels (key = build)", + Desc: "get labels (key = build)", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -200,7 +201,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"16\"},{\"build\":\"17\"}", }, { - caseDesc: "get labels (key = build) with page", + Desc: "get labels (key = build) with page", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -210,7 +211,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"17\"}", }, { - caseDesc: "get labels (key = build && env = production)", + Desc: "get labels (key = build && env = production)", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -220,7 +221,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"}", }, { - caseDesc: "get labels (key = build && env = production) with page", + Desc: "get labels (key = build && env = production) with page", Object: ManagerApiExpect(t), Method: http.MethodGet, Headers: map[string]string{"Authorization": token}, @@ -230,7 +231,7 @@ func TestLabel(t *testing.T) { ExpectBody: "{\"env\":\"production\"}", }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -238,7 +239,7 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/c1", @@ -246,7 +247,7 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete service", + Desc: "delete service", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/services/s1", @@ -254,7 +255,7 @@ func TestLabel(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete upstream", + Desc: "delete upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/u1", @@ -264,6 +265,6 @@ func TestLabel(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_online_debug_test.go b/api/test/e2e/route_online_debug_test.go index dc5bdaa41b..4796d20fb6 100644 --- a/api/test/e2e/route_online_debug_test.go +++ b/api/test/e2e/route_online_debug_test.go @@ -30,7 +30,7 @@ import ( func TestRoute_Online_Debug_Route_Not_Exist(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "hit route that not exist", + Desc: "hit route that not exist", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -39,7 +39,7 @@ func TestRoute_Online_Debug_Route_Not_Exist(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } basepath := "http://127.0.0.1:9000/apisix/admin/debug-request-forwarding" request, _ := http.NewRequest("POST", basepath, strings.NewReader(`{"url": "`+APISIXInternalUrl+`/hello_","method": "GET","request_protocol": "http"}`)) @@ -57,18 +57,19 @@ func TestRoute_Online_Debug_Route_Not_Exist(t *testing.T) { func TestRoute_Online_Debug_Route_With_Query_Params(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "hit route that not exist", + Desc: "hit route that not exist", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", ExpectStatus: http.StatusNotFound, ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n", + Sleep: sleepTime, }, { - caseDesc: "create route with query params", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with query params", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -86,13 +87,12 @@ func TestRoute_Online_Debug_Route_With_Query_Params(t *testing.T) { }`, Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, - Sleep: sleepTime, }, { - caseDesc: "online debug route with query params", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with query params", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello?name=aaa", "request_protocol": "http", @@ -100,9 +100,10 @@ func TestRoute_Online_Debug_Route_With_Query_Params(t *testing.T) { }`, Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, + Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -110,7 +111,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -121,14 +122,14 @@ func TestRoute_Online_Debug_Route_With_Query_Params(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -137,10 +138,10 @@ func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route with header params", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with header params", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -161,10 +162,10 @@ func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "online debug route with header params", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with header params", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello", "request_protocol": "http", @@ -177,7 +178,7 @@ func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -185,7 +186,7 @@ func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -196,14 +197,14 @@ func TestRoute_Online_Debug_Route_With_Header_Params(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -212,10 +213,10 @@ func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route with method POST", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with method POST", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["POST"], @@ -233,10 +234,10 @@ func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "online debug route with body params", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with body params", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello", "request_protocol": "http", @@ -250,7 +251,7 @@ func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -258,7 +259,7 @@ func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -269,14 +270,14 @@ func TestRoute_Online_Debug_Route_With_Body_Params(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -285,10 +286,10 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route enable basic-auth plugin", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route enable basic-auth plugin", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -309,7 +310,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "make sure the consumer is not created", + Desc: "make sure the consumer is not created", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -317,10 +318,10 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPost, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -337,10 +338,10 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "online debug route with username and password", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with username and password", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello", "request_protocol": "http", @@ -355,7 +356,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // online debug without basic-auth @@ -374,7 +375,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { // clear test data tests = []HttpTestCase{ { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -382,7 +383,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with the jwt token from just deleted consumer", + Desc: "verify route with the jwt token from just deleted consumer", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -392,7 +393,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -400,7 +401,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -411,14 +412,14 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -427,10 +428,10 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route enable jwt-auth plugin", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route enable jwt-auth plugin", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -451,7 +452,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "make sure the consumer is not created", + Desc: "make sure the consumer is not created", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -460,10 +461,10 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -481,7 +482,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } time.Sleep(sleepTime) @@ -494,10 +495,10 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "online debug route with jwt token", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with jwt token", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello", "request_protocol": "http", @@ -512,7 +513,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // online debug without jwt-auth @@ -531,7 +532,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { // clear test data tests = []HttpTestCase{ { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -539,7 +540,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with the jwt token from just deleted consumer", + Desc: "verify route with the jwt token from just deleted consumer", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -549,7 +550,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -557,7 +558,7 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -568,14 +569,14 @@ func TestRoute_Online_Debug_Route_With_Jwt_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -583,10 +584,10 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route enable key-auth plugin", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route enable key-auth plugin", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -606,7 +607,7 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the consumer is not created", + Desc: "make sure the consumer is not created", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -614,10 +615,10 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -631,10 +632,10 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "online debug route with apikey", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with apikey", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello", "request_protocol": "http", @@ -649,7 +650,7 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // online debug without key-auth @@ -668,7 +669,7 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { // clear test data tests = []HttpTestCase{ { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -676,7 +677,7 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with the jwt token from just deleted consumer", + Desc: "verify route with the jwt token from just deleted consumer", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -686,7 +687,7 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -694,7 +695,7 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -705,14 +706,14 @@ func TestRoute_Online_Debug_Route_With_Key_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -720,10 +721,10 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route enable key-auth plugin", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route enable key-auth plugin", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -746,7 +747,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the consumer is not created", + Desc: "make sure the consumer is not created", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -754,10 +755,10 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -771,10 +772,10 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "online debug route with apikey", - Object: ManagerApiExpect(t), - Method: http.MethodPost, - Path: "/apisix/admin/debug-request-forwarding", + Desc: "online debug route with apikey", + Object: ManagerApiExpect(t), + Method: http.MethodPost, + Path: "/apisix/admin/debug-request-forwarding", Body: `{ "url": "` + APISIXInternalUrl + `/hello?name=aaa", "request_protocol": "http", @@ -789,7 +790,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // online debug without key-auth @@ -808,7 +809,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { // clear test data tests = []HttpTestCase{ { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -816,7 +817,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with the jwt token from just deleted consumer", + Desc: "verify route with the jwt token from just deleted consumer", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -827,7 +828,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -835,7 +836,7 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -846,6 +847,6 @@ func TestRoute_Online_Debug_Route_With_Query_Params_Key_Auth(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_remote_addr_test.go b/api/test/e2e/route_remote_addr_test.go index 7bceed0e79..d53c894add 100644 --- a/api/test/e2e/route_remote_addr_test.go +++ b/api/test/e2e/route_remote_addr_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_add_with_invalid_remote_addr(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "config route with invalid remote_addr", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "config route with invalid remote_addr", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addr": "127.0.0.", @@ -45,7 +45,7 @@ func TestRoute_add_with_invalid_remote_addr(t *testing.T) { ExpectBody: "\"code\":10000,\"message\":\"schema validate failed: remote_addr: Must validate at least one schema (anyOf)\\nremote_addr: Does not match format 'ipv4'\"", }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -54,10 +54,10 @@ func TestRoute_add_with_invalid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "config route with invalid remote_addr", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "config route with invalid remote_addr", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addr": "127.0.0.aa", @@ -75,7 +75,7 @@ func TestRoute_add_with_invalid_remote_addr(t *testing.T) { ExpectBody: "\"code\":10000,\"message\":\"schema validate failed: remote_addr: Must validate at least one schema (anyOf)\\nremote_addr: Does not match format 'ipv4'\"", }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -84,10 +84,10 @@ func TestRoute_add_with_invalid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "config route with invalid remote_addrs", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "config route with invalid remote_addrs", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addrs": ["127.0.0.1","192.168.0."], @@ -105,7 +105,7 @@ func TestRoute_add_with_invalid_remote_addr(t *testing.T) { ExpectBody: "\"code\":10000,\"message\":\"schema validate failed: remote_addrs.1: Must validate at least one schema (anyOf)\\nremote_addrs.1: Does not match format 'ipv4'\"", }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -116,6 +116,6 @@ func TestRoute_add_with_invalid_remote_addr(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_service_upstream_test.go b/api/test/e2e/route_service_upstream_test.go index 39a05fd36c..0e8bf64a2e 100644 --- a/api/test/e2e/route_service_upstream_test.go +++ b/api/test/e2e/route_service_upstream_test.go @@ -27,10 +27,10 @@ import ( func TestRoute_Invalid_Service_And_Service(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "use service that not exist - dashboard", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "use service that not exist - dashboard", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "service_id": "not-exists" @@ -39,17 +39,17 @@ func TestRoute_Invalid_Service_And_Service(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "hit invalid route on data plane", + Desc: "hit invalid route on data plane", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", ExpectCode: http.StatusNotFound, }, { - caseDesc: "use upstream that not exist", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "use upstream that not exist", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "upstream_id": "not-exists" @@ -58,17 +58,17 @@ func TestRoute_Invalid_Service_And_Service(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "hit invalid route on data plane", + Desc: "hit invalid route on data plane", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", ExpectCode: http.StatusNotFound, }, { - caseDesc: "create service and upstream together at the same time", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create service and upstream together at the same time", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "service_id": "not-exists-service", @@ -78,7 +78,7 @@ func TestRoute_Invalid_Service_And_Service(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "hit invalid route on data plane", + Desc: "hit invalid route on data plane", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -86,14 +86,14 @@ func TestRoute_Invalid_Service_And_Service(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Create_Service(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route has not created", + Desc: "make sure the route has not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -101,10 +101,10 @@ func TestRoute_Create_Service(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create service", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/services/200", + Desc: "create service", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/services/200", Body: `{ "upstream": { "type": "roundrobin", @@ -131,10 +131,10 @@ func TestRoute_Create_Service(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the service just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route using the service just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/server_port", "service_id": "200" @@ -145,7 +145,7 @@ func TestRoute_Create_Service(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // sleep for etcd sync @@ -162,7 +162,7 @@ func TestRoute_Create_Service(t *testing.T) { func TestRoute_Delete_Service(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -170,7 +170,7 @@ func TestRoute_Delete_Service(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "remove service", + Desc: "remove service", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/services/200", @@ -178,7 +178,7 @@ func TestRoute_Delete_Service(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit deleted route", + Desc: "hit deleted route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -186,17 +186,17 @@ func TestRoute_Delete_Service(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Create_Upstream(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create upstream", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create upstream", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [ { @@ -221,7 +221,7 @@ func TestRoute_Create_Upstream(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has not created", + Desc: "make sure the route has not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -229,10 +229,10 @@ func TestRoute_Create_Upstream(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -243,7 +243,7 @@ func TestRoute_Create_Upstream(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // sleep for etcd sync @@ -260,7 +260,7 @@ func TestRoute_Create_Upstream(t *testing.T) { func TestRoute_Delete_Upstream(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -268,7 +268,7 @@ func TestRoute_Delete_Upstream(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "remove upstream", + Desc: "remove upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/1", @@ -276,7 +276,7 @@ func TestRoute_Delete_Upstream(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit deleted route", + Desc: "hit deleted route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -284,6 +284,6 @@ func TestRoute_Delete_Upstream(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_test.go b/api/test/e2e/route_test.go index 7cc637d67e..15f680ec48 100644 --- a/api/test/e2e/route_test.go +++ b/api/test/e2e/route_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_Invalid_Host(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "invalid host", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "invalid host", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello_", "host": "$%$foo.com", @@ -42,10 +42,10 @@ func TestRoute_Invalid_Host(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "invalid hosts", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "invalid hosts", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "hosts": ["$%$foo.com", "*.bar.com"], @@ -60,10 +60,10 @@ func TestRoute_Invalid_Host(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "create route with host and hosts together at the same time", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with host and hosts together at the same time", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "host": "github.com", @@ -79,7 +79,7 @@ func TestRoute_Invalid_Host(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "hit route not created", + Desc: "hit route not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -88,7 +88,7 @@ func TestRoute_Invalid_Host(t *testing.T) { ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n", }, { - caseDesc: "hit route not created", + Desc: "hit route not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -99,14 +99,14 @@ func TestRoute_Invalid_Host(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Create_With_Hosts(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "hit route that not exist", + Desc: "hit route that not exist", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -115,10 +115,10 @@ func TestRoute_Create_With_Hosts(t *testing.T) { ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n", }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "hosts": ["foo.com", "*.bar.com"], @@ -133,10 +133,10 @@ func TestRoute_Create_With_Hosts(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route with int uri", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with int uri", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": 123456 }`, @@ -144,7 +144,7 @@ func TestRoute_Create_With_Hosts(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "hit the route just created - wildcard domain name", + Desc: "hit the route just created - wildcard domain name", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -154,7 +154,7 @@ func TestRoute_Create_With_Hosts(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just created", + Desc: "hit the route just created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -163,7 +163,7 @@ func TestRoute_Create_With_Hosts(t *testing.T) { ExpectBody: "hello world\n", }, { - caseDesc: "hit the route not exists", + Desc: "hit the route not exists", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_111", @@ -172,7 +172,7 @@ func TestRoute_Create_With_Hosts(t *testing.T) { ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n", }, { - caseDesc: "delete the route just created", + Desc: "delete the route just created", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -180,7 +180,7 @@ func TestRoute_Create_With_Hosts(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -192,14 +192,14 @@ func TestRoute_Create_With_Hosts(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Update_Routes_With_Hosts(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "hit route that not exist", + Desc: "hit route that not exist", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -208,10 +208,10 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n", }, { - caseDesc: "create route with host foo.com", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with host foo.com", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -229,7 +229,7 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just create", + Desc: "hit the route just create", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -238,10 +238,10 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route with host bar.com", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with host bar.com", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "hosts": ["bar.com"], @@ -256,7 +256,7 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route with host foo.com", + Desc: "hit the route with host foo.com", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -265,7 +265,7 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just updated", + Desc: "hit the route just updated", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -274,7 +274,7 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { ExpectBody: "hello world\n", }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -282,7 +282,7 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -294,14 +294,15 @@ func TestRoute_Update_Routes_With_Hosts(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Patch(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route not exists", + + Desc: "make sure the route not exists", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -309,10 +310,10 @@ func TestRoute_Patch(t *testing.T) { ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n", }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "upstream": { @@ -326,7 +327,7 @@ func TestRoute_Patch(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just created ", + Desc: "hit the route just created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -335,7 +336,7 @@ func TestRoute_Patch(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "route patch for update status(route offline)", + Desc: "route patch for update status(route offline)", Object: ManagerApiExpect(t), Method: http.MethodPatch, Path: "/apisix/admin/routes/r1", @@ -344,7 +345,7 @@ func TestRoute_Patch(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been offline", + Desc: "make sure the route has been offline", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -353,7 +354,7 @@ func TestRoute_Patch(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "route patch for update status (route online)", + Desc: "route patch for update status (route online)", Object: ManagerApiExpect(t), Method: http.MethodPatch, Path: "/apisix/admin/routes/r1/status", @@ -362,7 +363,7 @@ func TestRoute_Patch(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been online", + Desc: "make sure the route has been online", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -371,7 +372,7 @@ func TestRoute_Patch(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -379,7 +380,7 @@ func TestRoute_Patch(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -389,6 +390,119 @@ func TestRoute_Patch(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) + } +} + +//uris methods remote_addrs +func TestRoute_With_Empty_Array(t *testing.T) { + tests := []HttpTestCase{ + { + Desc: "create route with empty hosts and host", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "hosts": [], + "host": "test.com", + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + ExpectBody: `{"code":10000,"message":"schema validate failed: (root): Must validate one and only one schema (oneOf)\n(root): Must validate all the schemas (allOf)\nhosts: Array must have at least 1 items"}`, + }, + { + Desc: "make sure the route not created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + Headers: map[string]string{"Host": "test.com"}, + ExpectStatus: http.StatusNotFound, + ExpectBody: `{"error_msg":"404 Route Not Found"}`, + }, + { + Desc: "create route with empty hosts", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "hosts": [], + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + ExpectBody: `{"code":10000,"message":"schema validate failed: hosts: Array must have at least 1 items"}`, + }, + { + Desc: "make sure the route not created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusNotFound, + ExpectBody: `{"error_msg":"404 Route Not Found"}`, + }, + { + Desc: "create route with empty uris and uri", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "uris": [], + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + ExpectBody: `{"code":10000,"message":"schema validate failed: (root): Must validate one and only one schema (oneOf)\n(root): Must validate all the schemas (allOf)\nuris: Array must have at least 1 items"}`, + }, + { + Desc: "create route with empty remote_addrs and remote_addr", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "remote_addrs": [], + "remote_addr": "0.0.0.0", + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + ExpectBody: `{"code":10000,"message":"schema validate failed: (root): Must validate one and only one schema (oneOf)\n(root): Must validate all the schemas (allOf)\nremote_addrs: Array must have at least 1 items"}`, + }, + { + Desc: "make sure the route not created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusNotFound, + ExpectBody: `{"error_msg":"404 Route Not Found"}`, + }, + } + + for _, tc := range tests { + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_auth_plugin_test.go b/api/test/e2e/route_with_auth_plugin_test.go index 4b8195dcb4..ef5e290eb4 100644 --- a/api/test/e2e/route_with_auth_plugin_test.go +++ b/api/test/e2e/route_with_auth_plugin_test.go @@ -27,7 +27,7 @@ import ( func TestRoute_With_Auth_Plugin(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -35,10 +35,10 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -58,7 +58,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectBody: `"code":0`, }, { - caseDesc: "make sure the consumer is not created", + Desc: "make sure the consumer is not created", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -66,10 +66,10 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -87,7 +87,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } time.Sleep(sleepTime) @@ -106,7 +106,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { // verify token and clean test data tests = []HttpTestCase{ { - caseDesc: "verify route without jwt token", + Desc: "verify route without jwt token", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -115,7 +115,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route with correct jwt token", + Desc: "verify route with correct jwt token", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -124,7 +124,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "verify route with incorrect jwt token", + Desc: "verify route with incorrect jwt token", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -133,7 +133,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectBody: `{"message":"invalid jwt string"}`, }, { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -141,7 +141,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with the jwt token from just deleted consumer", + Desc: "verify route with the jwt token from just deleted consumer", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -151,7 +151,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -159,7 +159,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the deleted route ", + Desc: "verify the deleted route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -170,7 +170,7 @@ func TestRoute_With_Auth_Plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_limit_plugin_test.go b/api/test/e2e/route_with_limit_plugin_test.go index 58bd57d36f..ab3a4c0e48 100644 --- a/api/test/e2e/route_with_limit_plugin_test.go +++ b/api/test/e2e/route_with_limit_plugin_test.go @@ -25,7 +25,7 @@ import ( func TestRoute_With_Limit_Plugin(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -33,10 +33,10 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -61,7 +61,7 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { ExpectBody: `"code":0`, }, { - caseDesc: "verify route that should not be limited", + Desc: "verify route that should not be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -70,7 +70,7 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route that should not be limited 2", + Desc: "verify route that should not be limited 2", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -78,7 +78,7 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "verify route that should be limited", + Desc: "verify route that should be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -86,7 +86,7 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { ExpectBody: "503 Service Temporarily Unavailable", }, { - caseDesc: "verify route that should not be limited since time window pass", + Desc: "verify route that should not be limited since time window pass", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -95,7 +95,7 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { Sleep: 3 * time.Second, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -103,7 +103,7 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been deleted", + Desc: "make sure the route has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -114,14 +114,14 @@ func TestRoute_With_Limit_Plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -129,10 +129,10 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -158,7 +158,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectBody: `"code":0`, }, { - caseDesc: "make sure the consumer is not created", + Desc: "make sure the consumer is not created", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/consumers/jack", @@ -166,10 +166,10 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "create consumer", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "jack", "plugins": { @@ -182,10 +182,10 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create consumer 2", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/consumers", - Method: http.MethodPut, + Desc: "create consumer 2", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/consumers", + Method: http.MethodPut, Body: `{ "username": "pony", "plugins": { @@ -198,7 +198,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route that should not be limited", + Desc: "verify route that should not be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -208,7 +208,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route that should not be limited 2", + Desc: "verify route that should not be limited 2", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -217,7 +217,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "verify route that should be limited", + Desc: "verify route that should be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -226,7 +226,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectBody: "503 Service Temporarily Unavailable", }, { - caseDesc: "verify route that should not be limited (other consumer)", + Desc: "verify route that should not be limited (other consumer)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -235,7 +235,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "verify route that should not be limited since time window pass", + Desc: "verify route that should not be limited since time window pass", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -245,7 +245,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { Sleep: 2 * time.Second, }, { - caseDesc: "delete consumer pony", + Desc: "delete consumer pony", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/pony", @@ -253,7 +253,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete consumer jack", + Desc: "delete consumer jack", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -261,7 +261,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure pony has been deleted", + Desc: "make sure pony has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -271,7 +271,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "make sure jack has been deleted", + Desc: "make sure jack has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -280,7 +280,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectBody: `{"message":"Missing related consumer"}`, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -288,7 +288,7 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been deleted", + Desc: "make sure the route has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -299,14 +299,14 @@ func TestRoute_With_Limit_Plugin_By_Consumer(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -314,10 +314,10 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -343,7 +343,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: `"code":0`, }, { - caseDesc: "verify route that should not be limited", + Desc: "verify route that should not be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -352,7 +352,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route that should not be limited 2", + Desc: "verify route that should not be limited 2", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -360,7 +360,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "verify route that should be limited", + Desc: "verify route that should be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -368,7 +368,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: "503 Service Temporarily Unavailable", }, { - caseDesc: "verify route that should not be limited since time window pass", + Desc: "verify route that should not be limited since time window pass", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -377,10 +377,10 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { Sleep: 2 * time.Second, }, { - caseDesc: "update route to disable plugin limit-count", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route to disable plugin limit-count", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -406,7 +406,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: `"code":0`, }, { - caseDesc: "verify route that should not be limited", + Desc: "verify route that should not be limited", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -415,7 +415,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route that should not be limited (exceed config count)", + Desc: "verify route that should not be limited (exceed config count)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -423,7 +423,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "verify route that should not be limited (exceed config count again)", + Desc: "verify route that should not be limited (exceed config count again)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -431,7 +431,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -439,7 +439,7 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been deleted", + Desc: "make sure the route has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -450,6 +450,6 @@ func TestRoute_With_Limit_Count_And_Disable(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_log_plugin_test.go b/api/test/e2e/route_with_log_plugin_test.go index b770d621dc..2203d1b287 100644 --- a/api/test/e2e/route_with_log_plugin_test.go +++ b/api/test/e2e/route_with_log_plugin_test.go @@ -57,7 +57,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -65,10 +65,10 @@ func TestRoute_With_Log_Plugin(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "plugins": { @@ -97,7 +97,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access route to trigger log", + Desc: "access route to trigger log", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -108,7 +108,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // sleep for process log @@ -124,10 +124,10 @@ func TestRoute_With_Log_Plugin(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "create route with wrong https endpoint", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r2", + Desc: "create route with wrong https endpoint", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r2", Body: `{ "uri": "/hello", "plugins": { @@ -156,7 +156,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access route to trigger log", + Desc: "access route to trigger log", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -167,7 +167,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // sleep for process log @@ -185,7 +185,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -193,7 +193,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been deleted", + Desc: "make sure the route has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -202,7 +202,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route 2", + Desc: "delete route 2", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r2", @@ -210,7 +210,7 @@ func TestRoute_With_Log_Plugin(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route 2 has been deleted", + Desc: "make sure the route 2 has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -221,6 +221,6 @@ func TestRoute_With_Log_Plugin(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_management_fileds_test.go b/api/test/e2e/route_with_management_fileds_test.go index 59c40fd735..207cba92a2 100644 --- a/api/test/e2e/route_with_management_fileds_test.go +++ b/api/test/e2e/route_with_management_fileds_test.go @@ -29,10 +29,10 @@ import ( func TestRoute_with_name_desc(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "config route with name and desc (r1)", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "config route with name and desc (r1)", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello", "name": "jack", @@ -50,7 +50,7 @@ func TestRoute_with_name_desc(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route's uri (r1)", + Desc: "access the route's uri (r1)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -60,7 +60,7 @@ func TestRoute_with_name_desc(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify the route's content (r1)", + Desc: "verify the route's content (r1)", Object: ManagerApiExpect(t), Path: "/apisix/admin/routes/r1", Method: http.MethodGet, @@ -71,7 +71,7 @@ func TestRoute_with_name_desc(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } //get the route @@ -92,10 +92,10 @@ func TestRoute_with_name_desc(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "update the route (r1)", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "update the route (r1)", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello", "name": "new jack", @@ -115,7 +115,7 @@ func TestRoute_with_name_desc(t *testing.T) { }, { - caseDesc: "access the route's uri (r1)", + Desc: "access the route's uri (r1)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -127,7 +127,7 @@ func TestRoute_with_name_desc(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } //get the route (updated) @@ -146,7 +146,7 @@ func TestRoute_with_name_desc(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "delete the route (r1)", + Desc: "delete the route (r1)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -156,17 +156,17 @@ func TestRoute_with_name_desc(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_with_label(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "config route with labels (r1)", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "config route with labels (r1)", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello", "labels": { @@ -187,7 +187,7 @@ func TestRoute_with_label(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route's uri (r1)", + Desc: "access the route's uri (r1)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -197,7 +197,7 @@ func TestRoute_with_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify the route's detail (r1)", + Desc: "verify the route's detail (r1)", Object: ManagerApiExpect(t), Path: "/apisix/admin/routes/r1", Method: http.MethodGet, @@ -207,7 +207,7 @@ func TestRoute_with_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route (r1)", + Desc: "delete the route (r1)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -215,7 +215,7 @@ func TestRoute_with_label(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route after delete it", + Desc: "access the route after delete it", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -225,17 +225,17 @@ func TestRoute_with_label(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_search_by_label(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "config route with labels (r1)", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r1", - Method: http.MethodPut, + Desc: "config route with labels (r1)", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, Body: `{ "uri": "/hello", "labels": { @@ -256,10 +256,10 @@ func TestRoute_search_by_label(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "config route with labels (r2)", - Object: ManagerApiExpect(t), - Path: "/apisix/admin/routes/r2", - Method: http.MethodPut, + Desc: "config route with labels (r2)", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r2", + Method: http.MethodPut, Body: `{ "uri": "/hello2", "labels": { @@ -281,7 +281,7 @@ func TestRoute_search_by_label(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route's uri (r1)", + Desc: "access the route's uri (r1)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -291,7 +291,7 @@ func TestRoute_search_by_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify the route's detail (r1)", + Desc: "verify the route's detail (r1)", Object: ManagerApiExpect(t), Path: "/apisix/admin/routes/r1", Method: http.MethodGet, @@ -301,7 +301,7 @@ func TestRoute_search_by_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "search the route by label", + Desc: "search the route by label", Object: ManagerApiExpect(t), Path: "/apisix/admin/routes", Query: "label=build:16", @@ -312,7 +312,7 @@ func TestRoute_search_by_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "search the route by label (only key)", + Desc: "search the route by label (only key)", Object: ManagerApiExpect(t), Path: "/apisix/admin/routes", Query: "label=extra", @@ -323,7 +323,7 @@ func TestRoute_search_by_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "search the route by label (combination)", + Desc: "search the route by label (combination)", Object: ManagerApiExpect(t), Path: "/apisix/admin/routes", Query: "label=extra,build:16", @@ -334,7 +334,7 @@ func TestRoute_search_by_label(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route (r1)", + Desc: "delete the route (r1)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -342,7 +342,7 @@ func TestRoute_search_by_label(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete the route (r2)", + Desc: "delete the route (r2)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r2", @@ -350,7 +350,7 @@ func TestRoute_search_by_label(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route after delete it", + Desc: "access the route after delete it", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -360,6 +360,78 @@ func TestRoute_search_by_label(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) + } +} + +func TestRoute_With_Create_Time(t *testing.T) { + tests := []HttpTestCase{ + { + Desc: "create route with create_time", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "create_time": 1608792721, + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + }, + { + Desc: "create route with update_time", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "update_time": 1608792721, + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + }, + { + Desc: "create route with create_time and update_time", + Object: ManagerApiExpect(t), + Path: "/apisix/admin/routes/r1", + Method: http.MethodPut, + Body: `{ + "uri": "/hello", + "create_time": 1608792721, + "update_time": 1608792721, + "upstream": { + "nodes": { + "172.16.238.20:1980": 1 + }, + "type": "roundrobin" + } + }`, + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusBadRequest, + }, + { + Desc: "make sure the route not created", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", + ExpectStatus: http.StatusNotFound, + ExpectBody: `{"error_msg":"404 Route Not Found"}`, + }, + } + + for _, tc := range tests { + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_methods_test.go b/api/test/e2e/route_with_methods_test.go index a3d9d1ca77..07efdcc6bf 100644 --- a/api/test/e2e/route_with_methods_test.go +++ b/api/test/e2e/route_with_methods_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_with_methods(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "add route with invalid method", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with invalid method", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["TEST"], @@ -44,7 +44,7 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -53,10 +53,10 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "add route with valid method", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with valid method", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -73,7 +73,7 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -83,7 +83,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -91,10 +91,10 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "add route with valid methods", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with valid methods", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET", "POST", "PUT", "DELETE", "PATCH"], @@ -111,7 +111,7 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route by post", + Desc: "verify route by post", Object: APISIXExpect(t), Method: http.MethodPost, Path: "/hello", @@ -122,7 +122,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route by put", + Desc: "verify route by put", Object: APISIXExpect(t), Method: http.MethodPut, Path: "/hello", @@ -133,7 +133,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route by get", + Desc: "verify route by get", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -143,7 +143,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route by delete", + Desc: "verify route by delete", Object: APISIXExpect(t), Method: http.MethodDelete, Path: "/hello", @@ -153,7 +153,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route by patch", + Desc: "verify route by patch", Object: APISIXExpect(t), Method: http.MethodPatch, Path: "/hello", @@ -164,7 +164,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -172,10 +172,10 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "add route with lower case methods", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with lower case methods", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET", "post"], @@ -192,7 +192,7 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -201,10 +201,10 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "add route with methods GET", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with methods GET", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["GET"], @@ -221,7 +221,7 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route by get", + Desc: "verify route by get", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -231,7 +231,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route by post", + Desc: "verify route by post", Object: APISIXExpect(t), Method: http.MethodPost, Path: "/hello", @@ -241,10 +241,10 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route methods to POST", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route methods to POST", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "methods": ["POST"], @@ -261,7 +261,7 @@ func TestRoute_with_methods(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route by get", + Desc: "verify route by get", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -270,7 +270,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route by post", + Desc: "verify route by post", Object: APISIXExpect(t), Method: http.MethodPost, Path: "/hello", @@ -281,7 +281,7 @@ func TestRoute_with_methods(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -292,6 +292,6 @@ func TestRoute_with_methods(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_metric_plugin_test.go b/api/test/e2e/route_with_metric_plugin_test.go index 027e9ea18c..a654436dda 100644 --- a/api/test/e2e/route_with_metric_plugin_test.go +++ b/api/test/e2e/route_with_metric_plugin_test.go @@ -24,7 +24,7 @@ import ( func TestRoute_With_Plugin_Prometheus(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -32,10 +32,10 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -54,7 +54,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "fetch the prometheus metric data", + Desc: "fetch the prometheus metric data", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/apisix/prometheus/metrics", @@ -63,7 +63,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "request from client (200)", + Desc: "request from client (200)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -71,10 +71,10 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { ExpectBody: "hello world", }, { - caseDesc: "create route that uri not exists in upstream", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route that uri not exists in upstream", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello-not-exists", "plugins": { @@ -93,7 +93,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "request from client (404)", + Desc: "request from client (404)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello-not-exists", @@ -101,7 +101,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify the prometheus metric data (apisix_http_status 200)", + Desc: "verify the prometheus metric data (apisix_http_status 200)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/apisix/prometheus/metrics", @@ -110,7 +110,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify the prometheus metric data (apisix_http_status 404)", + Desc: "verify the prometheus metric data (apisix_http_status 404)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/apisix/prometheus/metrics", @@ -119,7 +119,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -127,7 +127,7 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been deleted", + Desc: "make sure the route has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -138,6 +138,6 @@ func TestRoute_With_Plugin_Prometheus(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_plugin_cors_test.go b/api/test/e2e/route_with_plugin_cors_test.go index d8afb919d1..a05e9637c3 100644 --- a/api/test/e2e/route_with_plugin_cors_test.go +++ b/api/test/e2e/route_with_plugin_cors_test.go @@ -24,7 +24,7 @@ import ( func TestRoute_With_Plugin_Cors(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created", + Desc: "make sure the route is not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -32,10 +32,10 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route with cors default setting", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route with cors default setting", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -54,7 +54,7 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with cors default setting", + Desc: "verify route with cors default setting", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -67,10 +67,10 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route with specified setting", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with specified setting", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -96,10 +96,10 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with cors specified setting", - Object: APISIXExpect(t), - Method: http.MethodGet, - Path: "/hello", + Desc: "verify route with cors specified setting", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", Headers: map[string]string{ "Origin": "http://sub2.domain.com", "resp-vary": "Via", @@ -116,10 +116,10 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route with cors specified no match origin", - Object: APISIXExpect(t), - Method: http.MethodGet, - Path: "/hello", + Desc: "verify route with cors specified no match origin", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", Headers: map[string]string{ "Origin": "http://sub3.domain.com", }, @@ -135,11 +135,11 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route with options method", - Object: APISIXExpect(t), - Method: http.MethodOptions, + Desc: "verify route with options method", + Object: APISIXExpect(t), + Method: http.MethodOptions, Headers: map[string]string{ - "Origin": "http://sub2.domain.com", + "Origin": "http://sub2.domain.com", }, Path: "/hello", ExpectStatus: http.StatusOK, @@ -153,10 +153,10 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { ExpectBody: "", }, { - caseDesc: "update route with cors setting force wildcard", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with cors setting force wildcard", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -180,10 +180,10 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route with cors setting force wildcard", - Object: APISIXExpect(t), - Method: http.MethodGet, - Path: "/hello", + Desc: "verify route with cors setting force wildcard", + Object: APISIXExpect(t), + Method: http.MethodGet, + Path: "/hello", Headers: map[string]string{ "Origin": "https://sub.domain.com", "ExternalHeader1": "val", @@ -204,7 +204,7 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -212,7 +212,7 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route deleted", + Desc: "make sure the route deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -223,7 +223,7 @@ func TestRoute_With_Plugin_Cors(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_plugin_orchestration_test.go b/api/test/e2e/route_with_plugin_orchestration_test.go index c6d729b52b..e980c100c2 100644 --- a/api/test/e2e/route_with_plugin_orchestration_test.go +++ b/api/test/e2e/route_with_plugin_orchestration_test.go @@ -36,7 +36,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created", + Desc: "make sure the route is not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -44,7 +44,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route with invalid dag config", + Desc: "create route with invalid dag config", Object: ManagerApiExpect(t), Method: http.MethodPut, Path: "/apisix/admin/routes/r1", @@ -53,7 +53,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "make sure the route created failed", + Desc: "make sure the route created failed", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -62,7 +62,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route with correct dag config", + Desc: "create route with correct dag config", Object: ManagerApiExpect(t), Method: http.MethodPut, Path: "/apisix/admin/routes/r1", @@ -71,7 +71,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify the route(should be blocked)", + Desc: "verify the route(should be blocked)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -81,7 +81,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify the route(should not be blocked)", + Desc: "verify the route(should not be blocked)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -89,7 +89,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { ExpectBody: `hello world`, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -97,7 +97,7 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -108,6 +108,6 @@ func TestRoute_With_Plugin_Orchestration(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_plugin_proxy_rewrite_test.go b/api/test/e2e/route_with_plugin_proxy_rewrite_test.go index 7f091612e1..a6d2898f0e 100644 --- a/api/test/e2e/route_with_plugin_proxy_rewrite_test.go +++ b/api/test/e2e/route_with_plugin_proxy_rewrite_test.go @@ -24,7 +24,7 @@ import ( func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created", + Desc: "make sure the route is not created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -32,10 +32,10 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route that will rewrite host and uri", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route that will rewrite host and uri", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -57,7 +57,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route that rewrite host and uri", + Desc: "verify route that rewrite host and uri", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -66,10 +66,10 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route that will rewrite headers", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route that will rewrite headers", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -93,7 +93,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route that rewrite headers", + Desc: "verify route that rewrite headers", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -103,10 +103,10 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route using regex_uri", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route using regex_uri", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/test/*", "plugins": { @@ -127,7 +127,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route that using regex_uri", + Desc: "verify route that using regex_uri", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/test/plugin/proxy/rewrite`, @@ -136,10 +136,10 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route that will rewrite args", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route that will rewrite args", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -160,7 +160,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route that rewrite args", + Desc: "verify route that rewrite args", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -170,7 +170,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -178,7 +178,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route deleted", + Desc: "make sure the route deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -189,7 +189,7 @@ func TestRoute_With_Plugin_Proxy_Rewrite(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_priority_test.go b/api/test/e2e/route_with_priority_test.go index 34860b4fa1..baf9abeb59 100644 --- a/api/test/e2e/route_with_priority_test.go +++ b/api/test/e2e/route_with_priority_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_with_priority(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "add another route with no priority (default 0)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add another route with no priority (default 0)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/server_port", "methods": ["GET"], @@ -44,7 +44,7 @@ func TestRoute_with_priority(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route", + Desc: "access the route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -53,10 +53,10 @@ func TestRoute_with_priority(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "add another route with valid priority (1), upstream is different from the others", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r2", + Desc: "add another route with valid priority (1), upstream is different from the others", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r2", Body: `{ "uri": "/server_port", "methods": ["GET"], @@ -74,7 +74,7 @@ func TestRoute_with_priority(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route to determine whether it meets the priority (compare 1 and default)", + Desc: "access the route to determine whether it meets the priority (compare 1 and default)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -83,7 +83,7 @@ func TestRoute_with_priority(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route (r1)", + Desc: "delete route (r1)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -92,7 +92,7 @@ func TestRoute_with_priority(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route (r2)", + Desc: "delete route (r2)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r2", @@ -103,6 +103,6 @@ func TestRoute_with_priority(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_trace_plugin_test.go b/api/test/e2e/route_with_trace_plugin_test.go index 3092087468..fb9f6a6ee5 100644 --- a/api/test/e2e/route_with_trace_plugin_test.go +++ b/api/test/e2e/route_with_trace_plugin_test.go @@ -27,7 +27,7 @@ import ( func TestRoute_With_Plugin_Skywalking(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "make sure the route is not created ", + Desc: "make sure the route is not created ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -35,10 +35,10 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { ExpectBody: `{"error_msg":"404 Route Not Found"}`, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -59,7 +59,7 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "tiger skywalking", + Desc: "tiger skywalking", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -70,7 +70,7 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // sleep for process log @@ -85,10 +85,10 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "update route to change sample ratio", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route to change sample ratio", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "plugins": { @@ -109,7 +109,7 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "access the route", + Desc: "access the route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -120,7 +120,7 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // sleep for process log @@ -135,7 +135,7 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -143,7 +143,7 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "make sure the route has been deleted", + Desc: "make sure the route has been deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -154,6 +154,6 @@ func TestRoute_With_Plugin_Skywalking(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_uri_uris_test.go b/api/test/e2e/route_with_uri_uris_test.go index c538b19505..60755a810e 100644 --- a/api/test/e2e/route_with_uri_uris_test.go +++ b/api/test/e2e/route_with_uri_uris_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_with_valid_uri_uris(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "add route with valid uri", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with valid uri", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "upstream": { @@ -43,7 +43,7 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route (r1)", + Desc: "hit the route (r1)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -53,7 +53,7 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route (r1)", + Desc: "delete the route (r1)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -62,10 +62,10 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "add route with valid uris", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with valid uris", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uris": ["/hello","/status"], "upstream": { @@ -81,7 +81,7 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route (/hello)", + Desc: "hit the route (/hello)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -91,7 +91,7 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route (/status)", + Desc: "hit the route (/status)", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/status", @@ -101,7 +101,7 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete the route (r1)", + Desc: "delete the route (r1)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -111,6 +111,6 @@ func TestRoute_with_valid_uri_uris(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_valid_remote_addr_test.go b/api/test/e2e/route_with_valid_remote_addr_test.go index 445fce1c1a..8c5f130f20 100644 --- a/api/test/e2e/route_with_valid_remote_addr_test.go +++ b/api/test/e2e/route_with_valid_remote_addr_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_with_valid_remote_addr(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "add route with valid remote_addr", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with valid remote_addr", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addr": "172.16.238.1", @@ -44,7 +44,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -54,10 +54,10 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route with valid remote_addr (CIDR)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with valid remote_addr (CIDR)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addr": "172.16.238.1/24", @@ -74,7 +74,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -84,10 +84,10 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update route with valid remote_addrs", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with valid remote_addrs", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addrs": ["172.16.238.1","192.168.0.2/24"], @@ -104,7 +104,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -114,10 +114,10 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update remote_addr to not be hit", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update remote_addr to not be hit", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addr": "10.10.10.10", @@ -134,7 +134,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -143,10 +143,10 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update remote_addrs to not be hit", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update remote_addrs to not be hit", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "remote_addrs": ["10.10.10.10","11.11.11.1/24"], @@ -163,7 +163,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -172,7 +172,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -181,7 +181,7 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify it again after deleting the route", + Desc: "verify it again after deleting the route", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -192,6 +192,6 @@ func TestRoute_with_valid_remote_addr(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/route_with_vars_test.go b/api/test/e2e/route_with_vars_test.go index c0b40d7ed3..faad3f2784 100644 --- a/api/test/e2e/route_with_vars_test.go +++ b/api/test/e2e/route_with_vars_test.go @@ -24,10 +24,10 @@ import ( func TestRoute_with_vars(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "add route with vars (args)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with vars (args)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "vars": [ @@ -47,7 +47,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with right args", + Desc: "hit the route with right args", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -57,7 +57,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with wrong args", + Desc: "hit the route with wrong args", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -67,7 +67,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with no args", + Desc: "hit the route with no args", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -76,10 +76,10 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "update route with vars (header)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with vars (header)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "vars": [ @@ -99,7 +99,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with right header", + Desc: "hit the route with right header", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"k": "header"}, @@ -109,7 +109,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with wrong header", + Desc: "hit the route with wrong header", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"k": "jack"}, @@ -119,7 +119,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with no header", + Desc: "hit the route with no header", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -128,10 +128,10 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "update route with vars (cookie)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "update route with vars (cookie)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "vars": [ @@ -151,7 +151,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with right Cookie", + Desc: "hit the route with right Cookie", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"Cookie": "_octo=GH1.1.572248189.1598928545; _device_id=2c1a1a52074e66a3a008e4b73c690500; logged_in=yes;"}, @@ -161,7 +161,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with wrong Cookie", + Desc: "hit the route with wrong Cookie", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"Cookie": "jack"}, @@ -171,7 +171,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with no Cookie", + Desc: "hit the route with no Cookie", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -180,7 +180,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -190,10 +190,10 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "add route with multiple vars (args, cookie and header)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with multiple vars (args, cookie and header)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "vars": [ @@ -215,7 +215,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with right parameters", + Desc: "hit the route with right parameters", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"k": "header", "Cookie": "_octo=GH1.1.572248189.1598928545; _device_id=2c1a1a52074e66a3a008e4b73c690500; logged_in=yes;"}, @@ -226,7 +226,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with wrong arg", + Desc: "hit the route with wrong arg", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"k": "header", "Cookie": "_octo=GH1.1.572248189.1598928545; _device_id=2c1a1a52074e66a3a008e4b73c690500; logged_in=yes;"}, @@ -236,7 +236,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with wrong header", + Desc: "hit the route with wrong header", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"k": "test", "Cookie": "_octo=GH1.1.572248189.1598928545; _device_id=2c1a1a52074e66a3a008e4b73c690500; logged_in=yes;"}, @@ -247,7 +247,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "hit the route with wrong cookie", + Desc: "hit the route with wrong cookie", Object: APISIXExpect(t), Method: http.MethodGet, Headers: map[string]string{"k": "header", "Cookie": "_octo=GH1.1.572248189.1598928545; logged_in=yes;"}, @@ -258,7 +258,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -268,10 +268,10 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "add route with vars (args is digital)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "add route with vars (args is digital)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "vars": [ @@ -291,7 +291,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "verify route", + Desc: "verify route", Object: APISIXExpect(t), Method: http.MethodGet, Path: `/hello`, @@ -301,7 +301,7 @@ func TestRoute_with_vars(t *testing.T) { }, { - caseDesc: "delete the route with vars (args is digital)", + Desc: "delete the route with vars (args is digital)", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", @@ -312,6 +312,6 @@ func TestRoute_with_vars(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/server_info_test.go b/api/test/e2e/server_info_test.go index bbe9c50f25..7eb45567f7 100644 --- a/api/test/e2e/server_info_test.go +++ b/api/test/e2e/server_info_test.go @@ -27,7 +27,7 @@ func TestServerInfo_Get(t *testing.T) { time.Sleep(2 * time.Second) testCases := []HttpTestCase{ { - caseDesc: "get server info", + Desc: "get server info", Object: ManagerApiExpect(t), Path: "/apisix/admin/server_info/apisix-server1", Method: http.MethodGet, @@ -36,7 +36,7 @@ func TestServerInfo_Get(t *testing.T) { ExpectBody: "\"hostname\":\"apisix_server1\"", }, { - caseDesc: "get server info", + Desc: "get server info", Object: ManagerApiExpect(t), Path: "/apisix/admin/server_info/apisix-server2", Method: http.MethodGet, @@ -47,14 +47,14 @@ func TestServerInfo_Get(t *testing.T) { } for _, tc := range testCases { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestServerInfo_List(t *testing.T) { testCases := []HttpTestCase{ { - caseDesc: "list all server info", + Desc: "list all server info", Object: ManagerApiExpect(t), Path: "/apisix/admin/server_info", Method: http.MethodGet, @@ -63,7 +63,7 @@ func TestServerInfo_List(t *testing.T) { ExpectBody: "\"total_size\":2", }, { - caseDesc: "list server info with hostname", + Desc: "list server info with hostname", Object: ManagerApiExpect(t), Path: "/apisix/admin/server_info", Query: "hostname=apisix_", @@ -73,7 +73,7 @@ func TestServerInfo_List(t *testing.T) { ExpectBody: "\"total_size\":2", }, { - caseDesc: "list server info with hostname", + Desc: "list server info with hostname", Object: ManagerApiExpect(t), Path: "/apisix/admin/server_info", Query: "hostname=apisix_server2", @@ -85,6 +85,6 @@ func TestServerInfo_List(t *testing.T) { } for _, tc := range testCases { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/ssl_test.go b/api/test/e2e/ssl_test.go index 5290fa3288..616890011e 100644 --- a/api/test/e2e/ssl_test.go +++ b/api/test/e2e/ssl_test.go @@ -66,7 +66,7 @@ func TestSSL_Basic(t *testing.T) { // main test cases tests := []HttpTestCase{ { - caseDesc: "create ssl fail - key and cert not match", + Desc: "create ssl fail - key and cert not match", Object: ManagerApiExpect(t), Method: http.MethodPost, Path: "/apisix/admin/ssl", @@ -75,7 +75,7 @@ func TestSSL_Basic(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "create ssl successfully", + Desc: "create ssl successfully", Object: ManagerApiExpect(t), Method: http.MethodPost, Path: "/apisix/admin/ssl", @@ -84,10 +84,10 @@ func TestSSL_Basic(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "create route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello_", "hosts": ["test2.com", "*.test2.com"], @@ -102,7 +102,16 @@ func TestSSL_Basic(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just created using HTTPS", + Desc: "get the route just created to trigger removing `key`", + Object: ManagerApiExpect(t), + Method: http.MethodGet, + Path: "/apisix/admin/routes/r1", + Headers: map[string]string{"Authorization": token}, + ExpectStatus: http.StatusOK, + Sleep: sleepTime, + }, + { + Desc: "hit the route just created using HTTPS", Object: APISIXHTTPSExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -112,10 +121,10 @@ func TestSSL_Basic(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "disable SSL", - Object: ManagerApiExpect(t), - Method: http.MethodPatch, - Path: "/apisix/admin/ssl/1", + Desc: "disable SSL", + Object: ManagerApiExpect(t), + Method: http.MethodPatch, + Path: "/apisix/admin/ssl/1", Body: `{ "status": 0 }`, @@ -125,7 +134,7 @@ func TestSSL_Basic(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // try again after disable SSL, make a HTTPS request @@ -138,7 +147,7 @@ func TestSSL_Basic(t *testing.T) { // enable SSL again tests = []HttpTestCase{ { - caseDesc: "enable SSL", + Desc: "enable SSL", Object: ManagerApiExpect(t), Method: http.MethodPatch, Path: "/apisix/admin/ssl/1/status", @@ -147,7 +156,7 @@ func TestSSL_Basic(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route using HTTPS, make sure enable successful", + Desc: "hit the route using HTTPS, make sure enable successful", Object: APISIXHTTPSExpect(t), Method: http.MethodGet, Path: "/hello_", @@ -158,19 +167,19 @@ func TestSSL_Basic(t *testing.T) { }, } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // delete SSL delSSL := HttpTestCase{ - caseDesc: "delete SSL", + Desc: "delete SSL", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/ssl/1", Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, } - testCaseCheck(delSSL) + testCaseCheck(delSSL, t) // try again after deleting SSL, make a HTTPS request // If use the test framework, errors will cause failure, so we need to make a separate https request for testing. @@ -181,12 +190,12 @@ func TestSSL_Basic(t *testing.T) { // clean test data delRoute := HttpTestCase{ - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/r1", Headers: map[string]string{"Authorization": token}, ExpectStatus: http.StatusOK, } - testCaseCheck(delRoute) + testCaseCheck(delRoute, t) } diff --git a/api/test/e2e/upstream_chash_hash_on_test.go b/api/test/e2e/upstream_chash_hash_on_test.go index c0c927c974..4d3a705e46 100644 --- a/api/test/e2e/upstream_chash_hash_on_test.go +++ b/api/test/e2e/upstream_chash_hash_on_test.go @@ -30,10 +30,10 @@ import ( func TestUpstream_chash_hash_on_custom_header(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with hash_on (custom_header)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with hash_on (custom_header)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -53,10 +53,10 @@ func TestUpstream_chash_hash_on_custom_header(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -68,7 +68,7 @@ func TestUpstream_chash_hash_on_custom_header(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -102,10 +102,10 @@ func TestUpstream_chash_hash_on_custom_header(t *testing.T) { func TestUpstream_chash_hash_on_cookie(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with hash_on (cookie)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with hash_on (cookie)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -127,7 +127,7 @@ func TestUpstream_chash_hash_on_cookie(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -181,10 +181,10 @@ func TestUpstream_chash_hash_on_cookie(t *testing.T) { func TestUpstream_key_contains_uppercase_letters_and_hyphen(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with key contains uppercase letters and hyphen", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with key contains uppercase letters and hyphen", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -206,7 +206,7 @@ func TestUpstream_key_contains_uppercase_letters_and_hyphen(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -240,10 +240,10 @@ func TestUpstream_key_contains_uppercase_letters_and_hyphen(t *testing.T) { func TestUpstream_chash_hash_on_consumer(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create consumer with key-auth", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/consumers", + Desc: "create consumer with key-auth", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/consumers", Body: `{ "username": "jack", "plugins": { @@ -256,10 +256,10 @@ func TestUpstream_chash_hash_on_consumer(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route with key-auth", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route with key-auth", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "plugins": { @@ -287,7 +287,7 @@ func TestUpstream_chash_hash_on_consumer(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -321,10 +321,10 @@ func TestUpstream_chash_hash_on_consumer(t *testing.T) { func TestUpstream_chash_hash_on_wrong_key(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with wrong key", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/2", + Desc: "create chash upstream with wrong key", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/2", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -344,7 +344,7 @@ func TestUpstream_chash_hash_on_wrong_key(t *testing.T) { ExpectBody: "schema validate failed: (root): Does not match pattern '^((uri|server_name|server_addr|request_uri|remote_port|remote_addr|query_string|host|hostname)|arg_[0-9a-zA-z_-]+)", }, { - caseDesc: "verify upstream with wrong key", + Desc: "verify upstream with wrong key", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/routes/2", @@ -355,7 +355,7 @@ func TestUpstream_chash_hash_on_wrong_key(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } @@ -363,10 +363,10 @@ func TestUpstream_chash_hash_on_wrong_key(t *testing.T) { func TestUpstream_chash_hash_on_vars(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream hash_on (vars)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream hash_on (vars)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -386,7 +386,7 @@ func TestUpstream_chash_hash_on_vars(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "verify upstream", + Desc: "verify upstream", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/upstreams/1", @@ -396,10 +396,10 @@ func TestUpstream_chash_hash_on_vars(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -409,7 +409,7 @@ func TestUpstream_chash_hash_on_vars(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "verify route", + Desc: "verify route", Object: ManagerApiExpect(t), Method: http.MethodGet, Path: "/apisix/admin/routes/1", @@ -421,7 +421,7 @@ func TestUpstream_chash_hash_on_vars(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -450,7 +450,7 @@ func TestUpstream_chash_hash_on_vars(t *testing.T) { func TestUpstream_Delete_hash_on(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "delete consumer", + Desc: "delete consumer", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/consumers/jack", @@ -458,7 +458,7 @@ func TestUpstream_Delete_hash_on(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/1", @@ -466,7 +466,7 @@ func TestUpstream_Delete_hash_on(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete upstream", + Desc: "delete upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/1", @@ -474,7 +474,7 @@ func TestUpstream_Delete_hash_on(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -485,6 +485,6 @@ func TestUpstream_Delete_hash_on(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/upstream_chash_query_string_arg_xxx_test.go b/api/test/e2e/upstream_chash_query_string_arg_xxx_test.go index 08a60350f9..02e5149085 100644 --- a/api/test/e2e/upstream_chash_query_string_arg_xxx_test.go +++ b/api/test/e2e/upstream_chash_query_string_arg_xxx_test.go @@ -30,10 +30,10 @@ import ( func TestUpstream_chash_query_string(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with key (query_string)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with key (query_string)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -57,10 +57,10 @@ func TestUpstream_chash_query_string(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -72,7 +72,7 @@ func TestUpstream_chash_query_string(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -106,10 +106,10 @@ func TestUpstream_chash_query_string(t *testing.T) { func TestUpstream_chash_arg_xxx(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with key (arg_xxx)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with key (arg_xxx)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -135,7 +135,7 @@ func TestUpstream_chash_arg_xxx(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } // hit routes @@ -169,7 +169,7 @@ func TestUpstream_chash_arg_xxx(t *testing.T) { func TestUpstream_Delete_chash(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/1", @@ -177,7 +177,7 @@ func TestUpstream_Delete_chash(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete upstream", + Desc: "delete upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/1", @@ -185,7 +185,7 @@ func TestUpstream_Delete_chash(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello1", @@ -196,6 +196,6 @@ func TestUpstream_Delete_chash(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/e2e/upstream_test.go b/api/test/e2e/upstream_test.go index beb0a8c1d6..2f947f0476 100644 --- a/api/test/e2e/upstream_test.go +++ b/api/test/e2e/upstream_test.go @@ -28,10 +28,10 @@ import ( func TestUpstream_Create(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "use upstream that not exist", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/r1", + Desc: "use upstream that not exist", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/r1", Body: `{ "uri": "/hello", "upstream_id": "not-exists" @@ -40,10 +40,10 @@ func TestUpstream_Create(t *testing.T) { ExpectStatus: http.StatusBadRequest, }, { - caseDesc: "create upstream", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create upstream", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -56,10 +56,10 @@ func TestUpstream_Create(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/hello", "upstream_id": "1" @@ -69,7 +69,7 @@ func TestUpstream_Create(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route just created", + Desc: "hit the route just created", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -80,17 +80,17 @@ func TestUpstream_Create(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestUpstream_Update(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "update upstream with domain", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "update upstream with domain", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -103,7 +103,7 @@ func TestUpstream_Update(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route using upstream 1", + Desc: "hit the route using upstream 1", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello", @@ -114,17 +114,17 @@ func TestUpstream_Update(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestRoute_Node_Host(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "update upstream - pass host: node", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "update upstream - pass host: node", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "httpbin.org", @@ -138,10 +138,10 @@ func TestRoute_Node_Host(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "update path for route", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "update path for route", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/*", "upstream_id": "1" @@ -150,7 +150,7 @@ func TestRoute_Node_Host(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route ", + Desc: "hit the route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/get", @@ -159,10 +159,10 @@ func TestRoute_Node_Host(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "update upstream - pass host: rewrite", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "update upstream - pass host: rewrite", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -177,7 +177,7 @@ func TestRoute_Node_Host(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route ", + Desc: "hit the route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/uri", @@ -188,17 +188,17 @@ func TestRoute_Node_Host(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } func TestUpstream_chash_remote_addr(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "create chash upstream with key (remote_addr)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with key (remote_addr)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [{ "host": "172.16.238.20", @@ -223,10 +223,10 @@ func TestUpstream_chash_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -238,7 +238,7 @@ func TestUpstream_chash_remote_addr(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } //hit routes @@ -265,10 +265,10 @@ func TestUpstream_chash_remote_addr(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "create chash upstream with key (remote_addr, weight equal 0 or 1)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with key (remote_addr, weight equal 0 or 1)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [ { @@ -294,10 +294,10 @@ func TestUpstream_chash_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -309,7 +309,7 @@ func TestUpstream_chash_remote_addr(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } //hit routes @@ -330,10 +330,10 @@ func TestUpstream_chash_remote_addr(t *testing.T) { tests = []HttpTestCase{ { - caseDesc: "create chash upstream with key (remote_addr, all weight equal 0)", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/upstreams/1", + Desc: "create chash upstream with key (remote_addr, all weight equal 0)", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/upstreams/1", Body: `{ "nodes": [ { @@ -354,10 +354,10 @@ func TestUpstream_chash_remote_addr(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "create route using the upstream just created", - Object: ManagerApiExpect(t), - Method: http.MethodPut, - Path: "/apisix/admin/routes/1", + Desc: "create route using the upstream just created", + Object: ManagerApiExpect(t), + Method: http.MethodPut, + Path: "/apisix/admin/routes/1", Body: `{ "uri": "/server_port", "upstream_id": "1" @@ -367,7 +367,7 @@ func TestUpstream_chash_remote_addr(t *testing.T) { Sleep: sleepTime, }, { - caseDesc: "hit the route ", + Desc: "hit the route ", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/server_port", @@ -378,7 +378,7 @@ func TestUpstream_chash_remote_addr(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } @@ -386,7 +386,7 @@ func TestUpstream_chash_remote_addr(t *testing.T) { func TestUpstream_Delete(t *testing.T) { tests := []HttpTestCase{ { - caseDesc: "delete not exist upstream", + Desc: "delete not exist upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/not-exist", @@ -394,7 +394,7 @@ func TestUpstream_Delete(t *testing.T) { ExpectStatus: http.StatusNotFound, }, { - caseDesc: "delete route", + Desc: "delete route", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/routes/1", @@ -402,7 +402,7 @@ func TestUpstream_Delete(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "delete upstream", + Desc: "delete upstream", Object: ManagerApiExpect(t), Method: http.MethodDelete, Path: "/apisix/admin/upstreams/1", @@ -410,7 +410,7 @@ func TestUpstream_Delete(t *testing.T) { ExpectStatus: http.StatusOK, }, { - caseDesc: "hit the route just deleted", + Desc: "hit the route just deleted", Object: APISIXExpect(t), Method: http.MethodGet, Path: "/hello1", @@ -421,6 +421,6 @@ func TestUpstream_Delete(t *testing.T) { } for _, tc := range tests { - testCaseCheck(tc) + testCaseCheck(tc, t) } } diff --git a/api/test/shell/cli_test.sh b/api/test/shell/cli_test.sh index 411130bd3a..60efafc889 100755 --- a/api/test/shell/cli_test.sh +++ b/api/test/shell/cli_test.sh @@ -40,7 +40,7 @@ clean_logfile() { trap clean_up EXIT export GO111MODULE=on -go build -o ./manager-api -ldflags "-X main.Version=${VERSION}" . +go build -o ./manager-api -ldflags "-X github.com/apisix/manager-api/cmd.Version=${VERSION}" ./cmd/manager # default level: warn, path: logs/error.log @@ -95,7 +95,7 @@ if [[ `grep -c "INFO" ./error.log` -eq '0' ]]; then exit 1 fi -# run on a different path +# run on a different path workDir=$(pwd) rm -rf html mkdir html @@ -155,7 +155,7 @@ sleep 6 cat ${logfile} -if [[ `grep -c "api/main.go:" ${logfile}` -ne '1' ]]; then +if [[ `grep -c "cmd/managerapi.go" ${logfile}` -ne '1' ]]; then echo "failed: failed to write the correct caller" exit 1 fi @@ -215,7 +215,7 @@ if [ -z "${token}" ]; then fi # more validation to make sure it's ok to access etcd -resp=$(curl -ig http://127.0.0.1:9000/apisix/admin/consumers -i -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}') +resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}') respCode=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 's/:/\n/g' | sed '1d') respMessage=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" | sed 's/:/\n/g' | sed '1d') if [ "$respCode" != "0" ] || [ $respMessage != "\"\"" ]; then diff --git a/web/config/routes.ts b/web/config/routes.ts index cfb01bc313..dac171691f 100644 --- a/web/config/routes.ts +++ b/web/config/routes.ts @@ -75,6 +75,18 @@ const routes = [ path: '/consumer/:username/edit', component: './Consumer/Create', }, + { + path: '/service/list', + component: './Service/List', + }, + { + path: '/service/create', + component: './Service/Create', + }, + { + path: '/service/:serviceId/edit', + component: './Service/Create', + }, { path: '/settings', component: './Setting', diff --git a/web/cypress/fixtures/certificate.json b/web/cypress/fixtures/certificate.json new file mode 100644 index 0000000000..a7a36d7752 --- /dev/null +++ b/web/cypress/fixtures/certificate.json @@ -0,0 +1,11 @@ +{ + "valid": { + "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\nDAtGaXNoZHJvd25lZDEcMBoGA1UEAwwTRmlzaGRyb3duZWQgUk9PVCBDQTAeFw0y\nMDExMDYwOTQ3NDhaFw0yMjExMDYwOTQ3NDhaMH8xCzAJBgNVBAYTAkNOMRIwEAYD\nVQQIDAlHdWFuZ2RvbmcxEjAQBgNVBAcMCUd1YW5nemhvdTEUMBIGA1UECgwLRmlz\naGRyb3duZWQxFzAVBgNVBAsMDnd3dy50ZXN0aGouY29tMRkwFwYDVQQDDBAqLnd3\ndy50ZXN0aGouY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzt2V\nU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0ohWMKzjmzauaMYXUDPfQ8y\nc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaWSNuPm73C26R6en/Jgu8I\n09c+gsBkhNykcnLevR5YPw2mOOKgLllmpCJsjqMkUUF1SLI503ZK2hVH6FdSntBS\nYDbQVJVQ8j3M71eKr/D8Z5wN4Px41Y2bTke+xXm/2x5YRkZdtLCx/rbXPnYLruhG\n/C7aLqlA/ykQV0AWQgu1tc5gnAcT3mb/3y7GlybC8poMNPcEWic05hBJhpxlDNll\nwmUpcLEI3orAfbZnBwIDAQABo4HSMIHPMAkGA1UdEwQCMAAwMwYJYIZIAYb4QgEN\nBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\nFgQUfETT6xM8b68g7gTGDoTMChRckhcwHwYDVR0jBBgwFoAUB160Cmr3uK3bPRJr\nQLm4zR+M4fEwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMCsGA1Ud\nEQQkMCKCECoud3d3LnRlc3Roai5jb22CDnd3dy50ZXN0aGouY29tMA0GCSqGSIb3\nDQEBCwUAA4IBAQBKhcUTzhgEwtbVfn1cmlH3sFpzs2Bp7LZNDbhvZHJHQv70lJzA\nIk3b8WyYu6WvAAQS90P2HVh5m8jeVLfZod+AF96F+b9tOn+VkuEQ7g4gIbn/NhWp\n/A8WFG7c6UvE3qQDBqN8UXRO3ZUlrweZwkCWQ6ioHzf+mw69xv7z1R/xo6Jcls7f\n7o/W5xXhGgFuJCutjAMf+5PkZsqo1XgpZbcD3as3vTZ2ynbZuWrtqquIKHoulL6z\n7aaDKz3NSgdSrGLwTRny8iDW6aGdDsWQGlOZV0Z6r9neFKimE0alUUyIn0j4raoD\nX+/an0a+Qq1jWejwU9R59Xdv0/fZWXzKmkeC\n-----END CERTIFICATE-----", + "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\nSNuPm73C26R6en/Jgu8I09c+gsBkhNykcnLevR5YPw2mOOKgLllmpCJsjqMkUUF1\nSLI503ZK2hVH6FdSntBSYDbQVJVQ8j3M71eKr/D8Z5wN4Px41Y2bTke+xXm/2x5Y\nRkZdtLCx/rbXPnYLruhG/C7aLqlA/ykQV0AWQgu1tc5gnAcT3mb/3y7GlybC8poM\nNPcEWic05hBJhpxlDNllwmUpcLEI3orAfbZnBwIDAQABAoIBAQCGvLCMP3iB0oOW\nLC4pAwelpuV+8d/MhOjajurCmEoKqMSs+K2roHVPKPt1uhMeeh4q+IEF+xC7Wz7t\nQgcIbBjDUlVcmFRqm4g4xeinBM8/WqGPQwETx15MNFb8tK7Jpv3beFGpmSKwCxvt\npcC+gq8tQtx7hSplFsb6KWS/N2S5qcEpQc2p4TrWBEJnmQXwXNhVytJltj+N3M+P\nR1XdzO2SsNE7v6XU9L6Yp4HfT8yJ9WvGa8A+hME+4gbKJxEx/hCzDc/7Wdci2Po4\ndZTKtyWQOpUHQyjh8Cs7Rc8MJWPIH0X5yg8rQggVa3Ouu+FWy6WhHEiEWfs1SUJY\nUV0bWm3hAoGBAOlc8qdX882wDfeaS140/ghUDN65rh502ee7MXRCW7doooDPfZ+S\np5qP1IW68JKKOW1hED/bR52AjlOKzSpo1htIWOODlfCEe/Ym0S8jA8F4CKQCko9C\npJOuebJdy9cY8BX4nip8u4FQp3GWUSTjHOmDl7UIJf6o1tdJRayE6hp5AoGBAOLu\noOz79yPykjIY2IZpyx1L7phWtM2g80j/QZJHX3rbXXn4t8KKSfS0ryApbjQHhNlF\nzC5nAcZb6Z/n8vZ8mwRji+FDWsEF5g/uYORhfdT0bISPnuRanSi8+hAkONjWlUzb\nkMO2njUECEdJXkAmb82ZMqnTrBenWzKLkWcjTC1/AoGAHAxc6forRoyjkSANcPxD\nkDKx/U8p+2UmD7EzJ3sWVPwRlBPcUIKq/GvPKmempKZScrAY6OPtPqQF90qWkENb\ngJn4fRgCvI7f610NBXJa8DUCLNxWSzvCVjHBVMvrRSYtLSbds9OcIdXU2lUr2Zgm\nkHaNlGevUWVvtR6MbkjnblkCgYEA1bf5FNdDbLZxmv6tRQFzifbOEOhvxMzU8qV7\nAqF3OYRI56smnO+SMQTNfZOnNxbxtZI3dmgKUt6TCsbumdbGQ37g6Nh/KxQ8FDrj\nQ5LRZ/J+FOYRtWvlYM2BEByc8RI+b7DFCJz/KFzQ0xo0ymOonc+u2CQCihBSIisx\nWBn1D08CgYEAybW4F0uPy0jMg7fJCXzNOnwurKyAH7Uej7ZCAOJ/I1RRdGo6A0bZ\nneuo3I758vX7jT6itMw/D35J5cm2DAAVgYhaECLg1qWTLaoJDcEQys5VmL6gBh8w\ngaY1BQkhja1FqA7OcEylRUUWFgO3bWvHchOagVZUyipnYaq5KSwNhvA=\n-----END RSA PRIVATE KEY-----", + "sni": "*.www.testhj.com" + }, + "invalid": { + "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\n-----END CERTIFICATE-----", + "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\n-----END RSA PRIVATE KEY-----" + } +} diff --git a/web/cypress/integration/consumer/create_and_delete_consumer.spec.js b/web/cypress/integration/consumer/create_and_delete_consumer.spec.js index 188d284415..bae929d706 100644 --- a/web/cypress/integration/consumer/create_and_delete_consumer.spec.js +++ b/web/cypress/integration/consumer/create_and_delete_consumer.spec.js @@ -36,17 +36,17 @@ context('Create and Delete Consumer', () => { cy.wait(sleepTime * 5); cy.contains('Create').click(); - // Basic Information + // basic information cy.get('#username').type(name); cy.get('#desc').type('desc_by_autotest'); cy.contains('Next').click(); cy.wait(sleepTime * 3); - // Plugin Config + // plugin config cy.contains(domSelectors.pluginsCard, 'key-auth').within(() => { cy.get('button').first().click(); }) - // edit CodeMirror + // edit codemirror cy.get('.CodeMirror') .first() .then((editor) => { @@ -57,6 +57,8 @@ context('Create and Delete Consumer', () => { }); cy.contains('button', 'Next').click(); cy.contains('button', 'Submit').click(); + cy.wait(sleepTime); + cy.get(domSelectors.notification).should('contain', 'Create Consumer Successfully'); }); it('delete the consumer', () => { @@ -75,17 +77,17 @@ context('Create and Delete Consumer', () => { cy.wait(sleepTime * 5); cy.contains('Create').click(); - // Basic Information + // basic information cy.get('#username').type(name); cy.get('#desc').type('desc_by_autotest'); cy.contains('Next').click(); cy.wait(sleepTime * 3); - // Plugin Config + // plugin config cy.contains(domSelectors.pluginsCard, 'key-auth').within(() => { cy.get('button').first().click(); }) - // edit CodeMirror + // edit codeMirror cy.get('.CodeMirror') .first() .then((editor) => { diff --git a/web/cypress/integration/route/create-and-delete-route.spec.js b/web/cypress/integration/route/create-and-delete-route.spec.js index ddd60beed0..c8bd6d99a6 100644 --- a/web/cypress/integration/route/create-and-delete-route.spec.js +++ b/web/cypress/integration/route/create-and-delete-route.spec.js @@ -56,10 +56,7 @@ context('Create and Delete Route', () => { // go to step2 cy.contains('Next').click(); - cy.wait(400); - cy.get('#nodes_0_host').type('12.12.12.12', { - timeout: 4000 - }); + cy.get('#nodes_0_host').type('12.12.12.12') // go to step3 cy.contains('Next').click(); diff --git a/web/cypress/integration/settings/settings-smoketest.spec.js b/web/cypress/integration/settings/settings-smoketest.spec.js new file mode 100644 index 0000000000..77b367691e --- /dev/null +++ b/web/cypress/integration/settings/settings-smoketest.spec.js @@ -0,0 +1,65 @@ +/* + * 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. + */ +/* eslint-disable no-undef */ + +context('settings page smoke test', () => { + const domSelectors = { + pageContent: '.ant-pro-page-container', + notificationMsg: '.ant-notification-notice-message' + }; + + beforeEach(() => { + // init login + cy.login(); + }) + + it('should visit settings page', () => { + // go to settings page + cy.visit('/'); + cy.contains('Settings').click(); + cy.wait(500); + cy.url().should('contains', '/settings'); + cy.get(domSelectors.pageContent) + .children() + .should('contain', 'Setting') + .and('contain', 'Grafana Address') + .and('contain', 'Grafana address should begin with HTTP or HTTPS') + }); + + it('should set a invaild url', () => { + cy.visit('/'); + cy.contains('Settings').click(); + cy.wait(500); + cy.url().should('contains', '/settings'); + cy.get('#grafanaURL').clear().type('httx://www.test.com'); + cy.get('.ant-form-item-explain').should('contain', 'Address is illegality'); + }); + + it('should set a accessible url', () => { + cy.visit('/'); + cy.contains('Settings').click(); + cy.wait(500); + cy.url().should('contains', '/settings'); + cy.get('#grafanaURL').clear().type('https://apisix.apache.org/'); + cy.contains('Submit').click(); + cy.get(domSelectors.notificationMsg).should('contain', 'Update Configuration Successfully'); + cy.wait(1000); + cy.get(domSelectors.pageContent) + .children() + .should('contain', 'Metrics') + }); +}) diff --git a/web/cypress/integration/ssl/ssl-smoketest.spec.js b/web/cypress/integration/ssl/ssl-smoketest.spec.js new file mode 100644 index 0000000000..307bb3bac0 --- /dev/null +++ b/web/cypress/integration/ssl/ssl-smoketest.spec.js @@ -0,0 +1,75 @@ +/* + * 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. + */ +/* eslint-disable no-undef */ + +context('ssl smoke test', () => { + const domSelectors = { + notificationDesc: '.ant-notification-notice-description', + notificationMsg: '.ant-notification-notice-message' + }; + + beforeEach(() => { + // init login + cy.login(); + cy.fixture('certificate.json').as('certificate'); + }) + + it('should set match certificate and key by input', function () { // use `function () if used `fixture` above` + // go to ssl create page + cy.visit('/'); + cy.contains('SSL').click(); + cy.wait(500); + cy.contains('Create').click(); + + const validCert = this.certificate.valid.cert; + const validKey = this.certificate.valid.key; + cy.get('#cert').type(validCert); + cy.get('#key').type(validKey); + + cy.contains('Next').click(); + cy.contains('Submit').click(); + cy.wait(500); + cy.url().should('contains', 'ssl/list'); + }); + + it('should delete the ssl record just created', function () { + cy.visit('/'); + cy.contains('SSL').click(); + cy.wait(500); + const sni = this.certificate.valid.sni; + cy.contains(sni).parents().contains('Delete').click(); + cy.contains('button', 'Confirm').click(); + cy.get(domSelectors.notificationMsg).should('contain', 'Remove target SSL successfully'); + }); + + it('should set unmatch certificate and key by input', function () { + // go to ssl create page + cy.visit('/'); + cy.contains('SSL').click(); + cy.wait(500); + cy.contains('Create').click(); + + const invalidCert = this.certificate.invalid.cert; + const invalidKey = this.certificate.invalid.key; + cy.get('#cert').type(invalidCert); + cy.get('#key').type(invalidKey); + + cy.contains('Next').click(); + cy.wait(100); + cy.get(domSelectors.notificationDesc).should('contain', "key and cert don't match"); + }); +}) diff --git a/web/src/components/Plugin/typing.d.ts b/web/src/components/Plugin/typing.d.ts index 3a899aa02b..1d8b7c809e 100644 --- a/web/src/components/Plugin/typing.d.ts +++ b/web/src/components/Plugin/typing.d.ts @@ -17,7 +17,7 @@ declare namespace PluginComponent { type Data = object; - type Schema = '' | 'route' | 'consumer'; + type Schema = '' | 'route' | 'consumer' | 'service'; type Category = | 'Security' diff --git a/web/src/components/Upstream/UpstreamForm.tsx b/web/src/components/Upstream/UpstreamForm.tsx index a6838e4a08..cf88245e35 100644 --- a/web/src/components/Upstream/UpstreamForm.tsx +++ b/web/src/components/Upstream/UpstreamForm.tsx @@ -26,6 +26,7 @@ import type { FormInstance } from 'antd/es/form'; enum Type { roundrobin = 'roundrobin', chash = 'chash', + ewma = 'ewma', } enum HashOn { @@ -97,7 +98,10 @@ const UpstreamForm: React.FC = forwardRef( useEffect(() => { const id = form.getFieldValue('upstream_id'); if (id) { - form.setFieldsValue(list.find((item) => item.id === id)); + setReadonly(true); + requestAnimationFrame(() => { + form.setFieldsValue(list.find((item) => item.id === id)); + }) } }, [list]); @@ -562,17 +566,23 @@ const UpstreamForm: React.FC = forwardRef( }} > {showSelector && ( - + { + setReadonly(Boolean(next.upstream_id)); + if (prev.upstream_id !== next.upstream_id) { + const id = next.upstream_id; + if (id) { + form.setFieldsValue(list.find((item) => item.id === id)); + form.setFieldsValue({ + upstream_id: id, + }); + } + } + return prev.upstream_id !== next.upstream_id; + }}> { + const { value, closable, onClose } = props; + return ( + + {value} + + ); + }} + > + {Object.keys(labelList).map((key) => { + return ( + + {(labelList[key] || []).map((value: string) => ( + + ))} + + ); + })} + + ); + } + }, { title: formatMessage({ id: 'page.route.status' }), dataIndex: 'status', @@ -98,8 +147,8 @@ const Page: React.FC = () => { {record.status ? ( {formatMessage({ id: 'page.route.published' })} ) : ( - {formatMessage({ id: 'page.route.unpublished' })} - )} + {formatMessage({ id: 'page.route.unpublished' })} + )} ), }, diff --git a/web/src/pages/Route/components/Step1/LabelsDrawer.tsx b/web/src/pages/Route/components/Step1/LabelsDrawer.tsx new file mode 100644 index 0000000000..6fb0a7033f --- /dev/null +++ b/web/src/pages/Route/components/Step1/LabelsDrawer.tsx @@ -0,0 +1,174 @@ +/* + * 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. + */ +import React, { useEffect, useState } from 'react'; +import { AutoComplete, Button, Col, Drawer, Form, notification, Row } from 'antd'; +import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; +import { useIntl } from 'umi'; + +import { transformLableValueToKeyValue } from '../../transform'; +import { fetchLabelList } from '../../service'; + +interface Props extends Pick { + labelsDataSource: string[]; + disabled: boolean; + onClose(): void; +} + +const LabelList = (disabled: boolean, labelList: RouteModule.LabelList) => { + const { formatMessage } = useIntl(); + + const keyOptions = Object.keys(labelList || {}).map((item) => ({ value: item })); + return ( + + {(fields, { add, remove }) => { + return ( + <> + {fields.map((field, index) => ( + + + + + + + + + + {({ getFieldValue }) => { + const key = getFieldValue(['labels', field.name, 'labelKey']); + let valueOptions = [{ value: '' }]; + if (labelList) { + valueOptions = (labelList[key] || []).map((item) => ({ value: item })); + } + + return ( + + + + ); + }} + + + + {!disabled && remove(field.name)} />} + + + + ))} + {!disabled && ( + + + + )} + + ); + }} + + ); +}; + +const LabelsDrawer: React.FC = ({ + disabled, + labelsDataSource, + onClose, + onChange = () => { }, +}) => { + const transformLabel = transformLableValueToKeyValue(labelsDataSource); + + const { formatMessage } = useIntl(); + const [form] = Form.useForm(); + const [labelList, setLabelList] = useState({}); + form.setFieldsValue({ labels: transformLabel }); + + useEffect(() => { + fetchLabelList().then(setLabelList); + }, []); + + return ( + + + + + } + > +
+ {LabelList(disabled, labelList || {})} +
+
+ ); +}; + +export default LabelsDrawer; diff --git a/web/src/pages/Route/components/Step1/MetaView.tsx b/web/src/pages/Route/components/Step1/MetaView.tsx index a7d86ebc75..8234be945f 100644 --- a/web/src/pages/Route/components/Step1/MetaView.tsx +++ b/web/src/pages/Route/components/Step1/MetaView.tsx @@ -14,17 +14,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; +import React, { useState } from 'react'; import Form from 'antd/es/form'; -import { Input, Switch } from 'antd'; +import { Input, Switch, Select, Button, Tag } from 'antd'; import { useIntl } from 'umi'; import { PanelSection } from '@api7-dashboard/ui'; -const MetaView: React.FC = ({ disabled, isEdit }) => { +import { FORM_ITEM_WITHOUT_LABEL } from '@/pages/Route/constants'; +import LabelsDrawer from './LabelsDrawer'; + +const MetaView: React.FC = ({ disabled, form, isEdit, onChange, }) => { const { formatMessage } = useIntl(); + const [visible, setVisible] = useState(false); return ( + {visible && ( + + {() => { + if (form.getFieldValue('labels')) { + return ( + setVisible(false)} + /> + ); + } + return null; + }} + + )} = ({ disabled, isEdit }) => disabled={disabled} /> + + + {/* TODO: value === '' means no service_id select, need to find a better way */} + None + {serviceList.map(item => { + return + {item.name} + + })} + + ); }; diff --git a/web/src/pages/Route/constants.ts b/web/src/pages/Route/constants.ts index 1082e5ec14..ab6c30cf73 100644 --- a/web/src/pages/Route/constants.ts +++ b/web/src/pages/Route/constants.ts @@ -43,6 +43,7 @@ export const FORM_ITEM_WITHOUT_LABEL = { export const DEFAULT_STEP_1_DATA: RouteModule.Form1Data = { name: '', desc: '', + labels:[], status: 1, priority: 0, websocket: false, diff --git a/web/src/pages/Route/locales/en-US.ts b/web/src/pages/Route/locales/en-US.ts index ebef2c253e..5dbd812003 100644 --- a/web/src/pages/Route/locales/en-US.ts +++ b/web/src/pages/Route/locales/en-US.ts @@ -31,6 +31,7 @@ export default { 'page.route.regexMatch': 'Regex Match', 'page.route.rule': 'Rule', 'page.route.httpHeaderName': 'HTTP Request Header Name', + 'page.route.service': 'Service', 'page.route.input.placeholder.parameterNameHttpHeader': 'Request header name, for example: HOST', 'page.route.input.placeholder.parameterNameRequestParameter': 'Parameter name, for example: id', diff --git a/web/src/pages/Route/locales/zh-CN.ts b/web/src/pages/Route/locales/zh-CN.ts index b2d7bc385d..040eaa2190 100644 --- a/web/src/pages/Route/locales/zh-CN.ts +++ b/web/src/pages/Route/locales/zh-CN.ts @@ -40,6 +40,7 @@ export default { 'page.route.published': '已发布', 'page.route.unpublished': '未发布', 'page.route.onlineDebug': '在线调试', + 'page.route.service': '服务', // button 'page.route.button.returnList': '返回路由列表', diff --git a/web/src/pages/Route/service.ts b/web/src/pages/Route/service.ts index 68eb6d3790..099428b021 100644 --- a/web/src/pages/Route/service.ts +++ b/web/src/pages/Route/service.ts @@ -17,7 +17,12 @@ import { request } from 'umi'; import { pickBy, identity } from 'lodash'; -import { transformStepData, transformRouteData, transformUpstreamNodes } from './transform'; +import { + transformStepData, + transformRouteData, + transformUpstreamNodes, + transformLabelList +} from './transform'; export const create = (data: RouteModule.RequestData) => request(`/routes`, { @@ -32,13 +37,15 @@ export const update = (rid: number, data: RouteModule.RequestData) => }); export const fetchItem = (rid: number) => - request(`/routes/${rid}`).then((data) => transformRouteData(data.data)); + request(`/routes/${rid}`).then((data) => (transformRouteData(data.data))); export const fetchList = ({ current = 1, pageSize = 10, ...res }) => { + const { labels } = res; return request>>('/routes', { params: { name: res.name, uri: res.uri, + label: (labels || []).join(','), page: current, page_size: pageSize, }, @@ -86,11 +93,13 @@ export const checkHostWithSSL = (hosts: string[]) => data: hosts, }); +export const fetchLabelList = () => + request('/labels/route').then(({ data }) => ((transformLabelList(data.rows)) as RouteModule.LabelList)); export const updateRouteStatus = (rid: string, status: RouteModule.RouteStatus) => request(`/routes/${rid}`, { method: 'PATCH', - data: {status} + data: { status } }); export const debugRoute = (data: RouteModule.debugRequest) => { @@ -99,3 +108,9 @@ export const debugRoute = (data: RouteModule.debugRequest) => { data, }); }; + +export const fetchServiceList = () => + request('/services').then(({ data }) => ({ + data: data.rows, + total: data.total_size, + })); diff --git a/web/src/pages/Route/transform.ts b/web/src/pages/Route/transform.ts index 1a325fffa1..c7b442de5b 100644 --- a/web/src/pages/Route/transform.ts +++ b/web/src/pages/Route/transform.ts @@ -16,6 +16,15 @@ */ import { omit, pick, cloneDeep } from 'lodash'; +export const transformLableValueToKeyValue = (data: string[]) => { + return (data || []).map((item) => { + const index = item.indexOf(':'); + const labelKey = item.substring(0, index); + const labelValue = item.substring(index + 1); + return { labelKey, labelValue, key: Math.random().toString(36).slice(2) }; + }); +}; + export const transformStepData = ({ form1Data, form2Data, @@ -35,8 +44,15 @@ export const transformStepData = ({ }; } + const labels = {}; + transformLableValueToKeyValue(form1Data.labels).forEach(item => { + labels[item.labelKey] = item.labelValue; + }) + const { service_id = '' } = form1Data; + const data: Partial = { - ...form1Data, + ...omit(form1Data, 'labels'), + labels, ...step3DataCloned, vars: advancedMatchingRules.map((rule) => { const { operator, position, name, value } = rule; @@ -83,6 +99,7 @@ export const transformStepData = ({ 'redirectURI', 'ret_code', 'redirectOption', + service_id.length === 0 ? 'service_id' : '', !Object.keys(step3DataCloned.plugins || {}).length ? 'plugins' : '', !Object.keys(step3DataCloned.script || {}).length ? 'script' : '', form1Data.hosts.filter(Boolean).length === 0 ? 'hosts' : '', @@ -103,6 +120,7 @@ export const transformStepData = ({ 'redirect', 'vars', 'plugins', + service_id.length !== 0 ? 'service_id' : '', form1Data.hosts.filter(Boolean).length !== 0 ? 'hosts' : '', data.remote_addrs?.filter(Boolean).length !== 0 ? 'remote_addrs' : '', ]); @@ -140,6 +158,7 @@ export const transformRouteData = (data: RouteModule.Body) => { const { name, desc, + labels, methods = [], uris, uri, @@ -150,6 +169,7 @@ export const transformRouteData = (data: RouteModule.Body) => { status, upstream, upstream_id, + service_id = '', priority = 0, enable_websocket } = data; @@ -160,10 +180,12 @@ export const transformRouteData = (data: RouteModule.Body) => { hosts: hosts || (host && [host]) || [''], uris: uris || (uri && [uri]) || [], remote_addrs: remote_addrs || [''], + labels: Object.keys(labels || []).map((item) => `${item}:${labels[item]}`), // @ts-ignore methods: methods.length ? methods : ["ALL"], priority, - enable_websocket + enable_websocket, + service_id }; const redirect = data.plugins?.redirect || {}; @@ -195,3 +217,24 @@ export const transformRouteData = (data: RouteModule.Body) => { advancedMatchingRules, }; }; + +export const transformLabelList = (data: RouteModule.ResponseLabelList) => { + if (!data) { + return {}; + } + const transformData = {}; + data.forEach((item) => { + const key = Object.keys(item)[0]; + const value = item[key]; + if (!transformData[key]) { + transformData[key] = []; + transformData[key].push(value); + return; + } + + if (transformData[key] && !transformData[key][value]) { + transformData[key].push(value); + } + }); + return transformData; +}; diff --git a/web/src/pages/Route/typing.d.ts b/web/src/pages/Route/typing.d.ts index 7710337474..f104b198a4 100644 --- a/web/src/pages/Route/typing.d.ts +++ b/web/src/pages/Route/typing.d.ts @@ -72,6 +72,7 @@ declare namespace RouteModule { id?: number; status: number; name: string; + labels: Record; desc: string; priority?: number; methods: HttpMethod[]; @@ -106,6 +107,7 @@ declare namespace RouteModule { script: Record; url?: string; enable_websocket?: boolean; + service_id?: string; }; // step1 @@ -117,13 +119,23 @@ declare namespace RouteModule { key: string; } + type ResponseLabelList = Record[]; + + type LabelList = Record; + + type LabelTableProps = { + labelKey: string, + labelValue: string, + key: string + } + type Step1PassProps = { form: FormInstance; advancedMatchingRules: MatchingRule[]; disabled?: boolean; isEdit?: boolean; onChange?(data: { - action: 'redirectOptionChange' | 'advancedMatchingRulesChange'; + action: 'redirectOptionChange' | 'advancedMatchingRulesChange' | 'labelsChange'; data: T; }): void; }; @@ -131,6 +143,7 @@ declare namespace RouteModule { type Form1Data = { name: string; desc: string; + labels: string[]; priority: number; websocket: boolean; hosts: string[]; @@ -142,6 +155,7 @@ declare namespace RouteModule { ret_code?: number; status: number; enable_websocket?: boolean; + service_id: string; }; type AdvancedMatchingRules = { @@ -162,7 +176,7 @@ declare namespace RouteModule { }; type Form2Data = { - type: 'roundrobin' | 'chash'; + type: 'roundrobin' | 'chash' | 'ewma'; hash_on?: string; key?: string; upstreamPath?: string; @@ -213,6 +227,7 @@ declare namespace RouteModule { remote_addrs: string[]; script: any; desc?: string; + labels: Record; upstream: { checks: UpstreamModule.HealthCheck; create_time: number; diff --git a/web/src/pages/Service/Create.tsx b/web/src/pages/Service/Create.tsx new file mode 100644 index 0000000000..3c8bf3a6fb --- /dev/null +++ b/web/src/pages/Service/Create.tsx @@ -0,0 +1,143 @@ +/* + * 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. + */ +import React, { useState, useRef, useEffect } from 'react' +import { useIntl, history } from 'umi'; +import { Card, Steps, Form, notification } from 'antd'; +import { PageHeaderWrapper } from '@ant-design/pro-layout'; +import { omit } from 'lodash'; + +import ActionBar from '@/components/ActionBar'; +import PluginPage from '@/components/Plugin'; +import { DEFAULT_UPSTREAM } from '@/components/Upstream'; +import Preview from './components/Preview'; +import Step1 from "./components/Step1"; +import { create, update, fetchItem } from './service'; + +const { Step } = Steps; + +const Page: React.FC = (props) => { + const { formatMessage } = useIntl(); + const [form] = Form.useForm(); + const [upstreamForm] = Form.useForm(); + const upstreamRef = useRef(); + const [plugins, setPlugins] = useState({}); + + const STEP_HEADER = [ + formatMessage({ id: 'page.service.steps.stepTitle.basicInformation' }), + formatMessage({ id: 'page.service.steps.stepTitle.pluginConfig' }), + formatMessage({ id: 'component.global.steps.stepTitle.preview' }), + ] + + const [stepHeader] = useState(STEP_HEADER); + const [step, setStep] = useState(1); + + useEffect(() => { + + // init upstream default value + upstreamForm.setFieldsValue(DEFAULT_UPSTREAM); + + const { serviceId } = (props as any).match.params; + if (serviceId) { + fetchItem(serviceId).then(({ data }) => { + if (data.upstream_id && data.upstream_id !== '') { + upstreamForm.setFieldsValue({ upstream_id: data.upstream_id }); + } + if (data.upstream) { + upstreamForm.setFieldsValue(data.upstream); + } + form.setFieldsValue(omit(data, ['upstream_id', 'upstream', 'plugins'])); + setPlugins(data.plugins || {}); + }); + } + }, []); + + const onSubmit = () => { + const data = { + ...form.getFieldsValue(), + plugins, + }; + + const upstreamFormData = upstreamForm.getFieldsValue(); + if (upstreamFormData.upstream_id === '') { + data.upstream = omit(upstreamFormData, ['upstream_id']); + } else { + data.upstream_id = upstreamFormData.upstream_id; + } + + const { serviceId } = (props as any).match.params; + (serviceId ? update(serviceId, data) : create(data)) + .then(() => { + notification.success({ + message: `${serviceId + ? formatMessage({ id: 'component.global.edit' }) + : formatMessage({ id: 'component.global.create' }) + } ${formatMessage({ id: 'menu.service' })} ${formatMessage({ + id: 'component.status.success', + })}`, + }); + history.push('/service/list'); + }) + .catch(() => { + setStep(3); + }); + }; + + const onStepChange = (nextStep: number) => { + if (step === 1 && nextStep === 2) { + form.validateFields().then(() => { + upstreamForm.validateFields().then(() => { + setStep(nextStep); + }) + }) + return; + } + if (nextStep === 4) { + onSubmit(); + return; + }; + setStep(nextStep); + } + + return (<> + + + + {stepHeader.map((item) => ( + + ))} + + {step === 1 && } + {step === 2 && ( + + )} + {step === 3 && } + + + + ) +} + +export default Page; diff --git a/web/src/pages/Service/List.tsx b/web/src/pages/Service/List.tsx new file mode 100644 index 0000000000..e3e5b99413 --- /dev/null +++ b/web/src/pages/Service/List.tsx @@ -0,0 +1,103 @@ +/* + * 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. + */ +import React, { useRef } from 'react'; +import { history, useIntl } from 'umi'; +import { PageHeaderWrapper } from '@ant-design/pro-layout'; +import ProTable, { ActionType, ProColumns } from '@ant-design/pro-table'; +import { PlusOutlined } from '@ant-design/icons'; +import { Button, notification, Popconfirm, Space } from 'antd'; + +import { fetchList, remove } from './service'; + +const Page: React.FC = () => { + const ref = useRef(); + const { formatMessage } = useIntl(); + + const columns: ProColumns[] = [ + { + title: 'ID', + dataIndex: 'id', + hideInSearch: true + }, + { + title: formatMessage({ id: 'component.global.name' }), + dataIndex: 'name', + }, + { + title: formatMessage({ id: 'component.global.description' }), + dataIndex: 'desc', + }, + { + title: formatMessage({ id: 'component.global.operation' }), + valueType: 'option', + hideInSearch: true, + render: (_, record) => ( + <> + + + { + remove(record.id!).then(() => { + notification.success({ + message: `${formatMessage({ id: 'component.global.delete' })} ${formatMessage({ + id: 'menu.service', + })} ${formatMessage({ id: 'component.status.success' })}`, + }); + /* eslint-disable no-unused-expressions */ + ref.current?.reload(); + }); + }} + okText={formatMessage({ id: 'component.global.confirm' })} + cancelText={formatMessage({ id: 'component.global.cancel' })} + > + + + + + ), + }, + ]; + + return ( + + actionRef={ref} + rowKey="id" + columns={columns} + request={fetchList} + toolBarRender={() => [ + , + ]} /> + ) +} + +export default Page; diff --git a/web/src/pages/Service/components/Preview.tsx b/web/src/pages/Service/components/Preview.tsx new file mode 100644 index 0000000000..5645224861 --- /dev/null +++ b/web/src/pages/Service/components/Preview.tsx @@ -0,0 +1,38 @@ +/* + * 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. + */ +import React from 'react'; +import { FormInstance } from 'antd/lib/form'; + +import PluginPage from '@/components/Plugin'; +import Step1 from './Step1'; + +type Props = { + form: FormInstance; + upstreamForm: FormInstance; + plugins: PluginComponent.Data; +}; + +const Page: React.FC = ({ form, plugins, upstreamForm }) => { + return ( + <> + + + + ); +}; + +export default Page; diff --git a/web/src/pages/Service/components/Step1.tsx b/web/src/pages/Service/components/Step1.tsx new file mode 100644 index 0000000000..d1f508d8ff --- /dev/null +++ b/web/src/pages/Service/components/Step1.tsx @@ -0,0 +1,71 @@ +/* + * 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. + */ +import React, { useEffect, useState } from 'react'; +import { Form, Input } from 'antd'; +import { useIntl } from 'umi'; + +import UpstreamForm from '@/components/Upstream'; +import { fetchUpstreamList } from '../service'; + +const FORM_LAYOUT = { + labelCol: { + span: 3, + }, + wrapperCol: { + span: 8, + }, +}; + +const Step1: React.FC = ({ + form, + upstreamForm, + upstreamRef, + disabled, +}) => { + const { formatMessage } = useIntl(); + const [list, setList] = useState([]); + useEffect(() => { + fetchUpstreamList().then(({ data }) => setList(data)); + }, []); + + return <> +
+ + + + + + +
+ + +} + +export default Step1; diff --git a/web/src/pages/Service/locales/en-US.ts b/web/src/pages/Service/locales/en-US.ts new file mode 100644 index 0000000000..2923865b73 --- /dev/null +++ b/web/src/pages/Service/locales/en-US.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ +export default { + 'page.service.steps.stepTitle.basicInformation': 'Basic Information', + 'page.service.steps.stepTitle.pluginConfig': 'Plugin Config', + 'page.service.steps.stepTitle.preview': 'Preview', +} diff --git a/web/src/pages/Service/locales/zh-CN.ts b/web/src/pages/Service/locales/zh-CN.ts new file mode 100644 index 0000000000..53fda037a3 --- /dev/null +++ b/web/src/pages/Service/locales/zh-CN.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ +export default { + 'page.service.steps.stepTitle.basicInformation': '基本信息', + 'page.service.steps.stepTitle.pluginConfig': '插件配置', + 'page.service.steps.stepTitle.preview': '预览', +} diff --git a/web/src/pages/Service/service.ts b/web/src/pages/Service/service.ts new file mode 100644 index 0000000000..1b541b29bb --- /dev/null +++ b/web/src/pages/Service/service.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ +import { request } from 'umi'; + +export const fetchList = ({ current = 1, pageSize = 10, ...res }) => + request('/services', { + params: { + name: res.name, + page: current, + page_size: pageSize, + }, + }).then(({ data }) => ({ + data: data.rows, + total: data.total_size, + })); + +export const fetchUpstreamList = () => { + return request>>('/upstreams').then(({ data }) => ({ + data: data.rows, + total: data.total_size, + })); +}; + +export const create = (data: ServiceModule.Entity) => + request('/services', { + method: 'POST', + data, + }); + +export const update = (serviceId: string, data: ServiceModule.Entity) => + request(`/services/${serviceId}`, { + method: 'PUT', + data, + }); + +export const remove = (serviceId: string) => request(`/services/${serviceId}`, { method: 'DELETE' }); + +export const fetchItem = (serviceId: number) => + request(`/services/${serviceId}`).then((data) => (data)); diff --git a/web/src/pages/Service/typing.d.ts b/web/src/pages/Service/typing.d.ts new file mode 100644 index 0000000000..a9e52d041a --- /dev/null +++ b/web/src/pages/Service/typing.d.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ +declare namespace ServiceModule { + + type Entity = { + name: string; + desc: string; + upstream: any; + upstream_id: string; + labels: string; + enable_websocket: boolean; + plugins: { + [name: string]: any; + }; + }; + + type ResponseBody = { + id: string, + plugins: Record, + upstream_id: string, + upstream: Record, + name: string, + desc: string, + enable_websocket: boolean, + } + + type Step1PassProps = { + form: FormInstance; + upstreamForm: FormInstance; + disabled?: boolean; + upstreamRef: any; + }; +}