feat: basic support Apache APISIX 2.13.0 (#2428)
diff --git a/api/conf/schema.json b/api/conf/schema.json
index a65c22a..fd88252 100644
--- a/api/conf/schema.json
+++ b/api/conf/schema.json
@@ -11,7 +11,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -97,7 +96,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -378,7 +376,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -931,7 +928,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -1161,7 +1157,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -1555,7 +1550,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -1815,7 +1809,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -2316,7 +2309,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -2857,7 +2849,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -3237,6 +3228,21 @@
}
],
"properties": {
+ "access_denied_redirect_uri": {
+ "maxLength": 2048,
+ "minLength": 1,
+ "type": "string"
+ },
+ "access_token_expires_in": {
+ "default": 300,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "access_token_expires_leeway": {
+ "default": 0,
+ "minimum": 0,
+ "type": "integer"
+ },
"audience": {
"description": "Deprecated, use `client_id` instead.",
"maxLength": 100,
@@ -3315,6 +3321,16 @@
],
"type": "string"
},
+ "refresh_token_expires_in": {
+ "default": 3600,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "refresh_token_expires_leeway": {
+ "default": 0,
+ "minimum": 0,
+ "type": "integer"
+ },
"resource_registration_endpoint": {
"maxLength": 4096,
"minLength": 1,
@@ -3542,6 +3558,97 @@
"scope": "global",
"version": 0.1
},
+ "clickhouse-logger": {
+ "metadata_schema": {
+ "properties": {
+ "log_format": {
+ "default": {
+ "@timestamp": "$time_iso8601",
+ "client_ip": "$remote_addr",
+ "host": "$host"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "priority": 398,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "properties": {
+ "batch_max_size": {
+ "default": 1000,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "buffer_duration": {
+ "default": 60,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "database": {
+ "default": "",
+ "type": "string"
+ },
+ "disable": {
+ "type": "boolean"
+ },
+ "endpoint_addr": {
+ "pattern": "^[^\\/]+:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?",
+ "type": "string"
+ },
+ "inactive_timeout": {
+ "default": 5,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "logtable": {
+ "default": "",
+ "type": "string"
+ },
+ "max_retry_count": {
+ "default": 0,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "name": {
+ "default": "clickhouse-logger",
+ "type": "string"
+ },
+ "password": {
+ "default": "",
+ "type": "string"
+ },
+ "retry_delay": {
+ "default": 1,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "ssl_verify": {
+ "default": true,
+ "type": "boolean"
+ },
+ "timeout": {
+ "default": 3,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "user": {
+ "default": "",
+ "type": "string"
+ }
+ },
+ "required": [
+ "database",
+ "endpoint_addr",
+ "logtable",
+ "password",
+ "user"
+ ],
+ "type": "object"
+ },
+ "version": 0.1
+ },
"client-control": {
"priority": 22000,
"schema": {
@@ -3651,6 +3758,18 @@
"version": 0.1
},
"cors": {
+ "metadata_schema": {
+ "properties": {
+ "allow_origins": {
+ "additionalProperties": {
+ "pattern": "^(\\*|\\*\\*|null|\\w+://[^,]+(,\\w+://[^,]+)*)$",
+ "type": "string"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
"priority": 4000,
"schema": {
"$comment": "this is a mark for our injected plugin schema",
@@ -3676,6 +3795,17 @@
"pattern": "^(\\*|\\*\\*|null|\\w+://[^,]+(,\\w+://[^,]+)*)$",
"type": "string"
},
+ "allow_origins_by_metadata": {
+ "description": "set allowed origins by referencing origins in plugin metadata",
+ "items": {
+ "maxLength": 4096,
+ "minLength": 1,
+ "type": "string"
+ },
+ "minItems": 1,
+ "type": "array",
+ "uniqueItems": true
+ },
"allow_origins_by_regex": {
"description": "you can use regex to allow specific origins when no credentials,for example use [.*\\.test.com] to allow a.test.com and b.test.com",
"items": {
@@ -3705,6 +3835,36 @@
},
"version": 0.1
},
+ "csrf": {
+ "priority": 2980,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "properties": {
+ "disable": {
+ "type": "boolean"
+ },
+ "expires": {
+ "default": 7200,
+ "description": "expires time(s) for csrf token",
+ "type": "integer"
+ },
+ "key": {
+ "description": "use to generate csrf token",
+ "type": "string"
+ },
+ "name": {
+ "default": "apisix-csrf-token",
+ "description": "the csrf token name",
+ "type": "string"
+ }
+ },
+ "required": [
+ "key"
+ ],
+ "type": "object"
+ },
+ "version": 0.1
+ },
"datadog": {
"metadata_schema": {
"properties": {
@@ -3870,6 +4030,11 @@
},
{
"required": [
+ "clickhouse"
+ ]
+ },
+ {
+ "required": [
"host",
"port"
]
@@ -3886,6 +4051,41 @@
"minimum": 1,
"type": "integer"
},
+ "clickhouse": {
+ "properties": {
+ "database": {
+ "default": "",
+ "type": "string"
+ },
+ "endpoint_addr": {
+ "1": {
+ "pattern": "^[^\\/]+:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?",
+ "type": "string"
+ },
+ "default": "http://127.0.0.1:8123"
+ },
+ "logtable": {
+ "default": "",
+ "type": "string"
+ },
+ "password": {
+ "default": "",
+ "type": "string"
+ },
+ "user": {
+ "default": "default",
+ "type": "string"
+ }
+ },
+ "required": [
+ "database",
+ "endpoint_addr",
+ "logtable",
+ "password",
+ "user"
+ ],
+ "type": "object"
+ },
"host": {
"1": {
"pattern": "^\\*?[0-9a-zA-Z-._]+$",
@@ -4199,6 +4399,38 @@
},
"version": 0.1
},
+ "file-logger": {
+ "metadata_schema": {
+ "properties": {
+ "log_format": {
+ "default": {
+ "@timestamp": "$time_iso8601",
+ "client_ip": "$remote_addr",
+ "host": "$host"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "priority": 399,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "properties": {
+ "disable": {
+ "type": "boolean"
+ },
+ "path": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "path"
+ ],
+ "type": "object"
+ },
+ "version": 0.1
+ },
"forward-auth": {
"priority": 2002,
"schema": {
@@ -4717,6 +4949,10 @@
"minimum": 0,
"type": "integer"
},
+ "ssl_verify": {
+ "default": false,
+ "type": "boolean"
+ },
"timeout": {
"default": 3,
"minimum": 1,
@@ -4914,8 +5150,20 @@
"schema": {
"$comment": "this is a mark for our injected plugin schema",
"properties": {
+ "cookie": {
+ "default": "jwt",
+ "type": "string"
+ },
"disable": {
"type": "boolean"
+ },
+ "header": {
+ "default": "authorization",
+ "type": "string"
+ },
+ "query": {
+ "default": "jwt",
+ "type": "string"
}
},
"type": "object"
@@ -5197,90 +5445,55 @@
"priority": 1002,
"schema": {
"$comment": "this is a mark for our injected plugin schema",
- "dependencies": {
- "policy": {
- "oneOf": [
- {
- "properties": {
- "policy": {
- "enum": [
- "local"
- ]
- }
- }
- },
- {
- "properties": {
- "policy": {
- "enum": [
- "redis"
- ]
- },
- "redis_database": {
- "default": 0,
- "minimum": 0,
- "type": "integer"
- },
- "redis_host": {
- "minLength": 2,
- "type": "string"
- },
- "redis_password": {
- "minLength": 0,
- "type": "string"
- },
- "redis_port": {
- "default": 6379,
- "minimum": 1,
- "type": "integer"
- },
- "redis_timeout": {
- "default": 1000,
- "minimum": 1,
- "type": "integer"
- }
- },
- "required": [
- "redis_host"
- ]
- },
- {
- "properties": {
- "policy": {
- "enum": [
- "redis-cluster"
- ]
- },
- "redis_cluster_name": {
- "type": "string"
- },
- "redis_cluster_nodes": {
- "items": {
- "maxLength": 100,
- "minLength": 2,
- "type": "string"
- },
- "minItems": 2,
- "type": "array"
- },
- "redis_password": {
- "minLength": 0,
- "type": "string"
- },
- "redis_timeout": {
- "default": 1000,
- "minimum": 1,
- "type": "integer"
- }
- },
- "required": [
- "redis_cluster_name",
- "redis_cluster_nodes"
+ "else": {
+ "if": {
+ "properties": {
+ "policy": {
+ "enum": [
+ "redis-cluster"
]
}
+ }
+ },
+ "then": {
+ "properties": {
+ "redis_cluster_name": {
+ "type": "string"
+ },
+ "redis_cluster_nodes": {
+ "items": {
+ "maxLength": 100,
+ "minLength": 2,
+ "type": "string"
+ },
+ "minItems": 2,
+ "type": "array"
+ },
+ "redis_password": {
+ "minLength": 0,
+ "type": "string"
+ },
+ "redis_timeout": {
+ "default": 1000,
+ "minimum": 1,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "redis_cluster_name",
+ "redis_cluster_nodes"
]
}
},
+ "if": {
+ "properties": {
+ "policy": {
+ "enum": [
+ "redis"
+ ]
+ }
+ }
+ },
"properties": {
"allow_degradation": {
"default": false,
@@ -5341,6 +5554,36 @@
"count",
"time_window"
],
+ "then": {
+ "properties": {
+ "redis_database": {
+ "default": 0,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "redis_host": {
+ "minLength": 2,
+ "type": "string"
+ },
+ "redis_password": {
+ "minLength": 0,
+ "type": "string"
+ },
+ "redis_port": {
+ "default": 6379,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "redis_timeout": {
+ "default": 1000,
+ "minimum": 1,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "redis_host"
+ ]
+ },
"type": "object"
},
"version": 0.4
@@ -5414,6 +5657,214 @@
"scope": "global",
"version": 0.1
},
+ "loggly": {
+ "metadata_schema": {
+ "properties": {
+ "host": {
+ "default": "logs-01.loggly.com",
+ "type": "string"
+ },
+ "log_format": {
+ "type": "object"
+ },
+ "port": {
+ "default": 514,
+ "type": "integer"
+ },
+ "protocol": {
+ "default": "syslog",
+ "enum": [
+ "http",
+ "https",
+ "syslog"
+ ],
+ "type": "string"
+ },
+ "timeout": {
+ "default": 5000,
+ "minimum": 1,
+ "type": "integer"
+ }
+ },
+ "type": "object"
+ },
+ "priority": 411,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "properties": {
+ "batch_max_size": {
+ "default": 1000,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "buffer_duration": {
+ "default": 60,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "customer_token": {
+ "type": "string"
+ },
+ "disable": {
+ "type": "boolean"
+ },
+ "inactive_timeout": {
+ "default": 5,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "include_req_body": {
+ "default": false,
+ "type": "boolean"
+ },
+ "include_resp_body": {
+ "default": false,
+ "type": "boolean"
+ },
+ "include_resp_body_expr": {
+ "items": {
+ "type": "array"
+ },
+ "minItems": 1,
+ "type": "array"
+ },
+ "max_retry_count": {
+ "default": 0,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "name": {
+ "default": "loggly",
+ "type": "string"
+ },
+ "retry_delay": {
+ "default": 1,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "severity": {
+ "default": "INFO",
+ "description": "base severity log level",
+ "enum": [
+ "ALERT",
+ "CRIT",
+ "DEBUG",
+ "EMEGR",
+ "ERR",
+ "INFO",
+ "NOTICE",
+ "WARNING",
+ "alert",
+ "crit",
+ "debug",
+ "emegr",
+ "err",
+ "info",
+ "notice",
+ "warning"
+ ],
+ "type": "string"
+ },
+ "severity_map": {
+ "additionalProperties": false,
+ "description": "upstream response code vs syslog severity mapping",
+ "patternProperties": {
+ "^[1-5][0-9]{2}$": {
+ "description": "keys are HTTP status code, values are severity",
+ "enum": [
+ "ALERT",
+ "CRIT",
+ "DEBUG",
+ "EMEGR",
+ "ERR",
+ "INFO",
+ "NOTICE",
+ "WARNING",
+ "alert",
+ "crit",
+ "debug",
+ "emegr",
+ "err",
+ "info",
+ "notice",
+ "warning"
+ ],
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ssl_verify": {
+ "default": true,
+ "type": "boolean"
+ },
+ "tags": {
+ "default": [
+ "apisix"
+ ],
+ "items": {
+ "pattern": "^(?!tag=)[ -~]*",
+ "type": "string"
+ },
+ "minItems": 1,
+ "type": "array"
+ }
+ },
+ "required": [
+ "customer_token"
+ ],
+ "type": "object"
+ },
+ "version": 0.1
+ },
+ "mocking": {
+ "priority": 10900,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "anyOf": [
+ {
+ "required": [
+ "response_example"
+ ]
+ },
+ {
+ "required": [
+ "response_schema"
+ ]
+ }
+ ],
+ "properties": {
+ "content_type": {
+ "default": "application/json;charset=utf8",
+ "type": "string"
+ },
+ "delay": {
+ "default": 0,
+ "type": "integer"
+ },
+ "disable": {
+ "type": "boolean"
+ },
+ "response_example": {
+ "type": "string"
+ },
+ "response_schema": {
+ "type": "object"
+ },
+ "response_status": {
+ "default": 200,
+ "minimum": 100,
+ "type": "integer"
+ },
+ "with_mock_header": {
+ "default": true,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "version": 0.1
+ },
"node-status": {
"priority": 1000,
"schema": {
@@ -5525,6 +5976,10 @@
"default": "/logout",
"type": "string"
},
+ "post_logout_redirect_uri": {
+ "description": "the URI will be redirect when request logout_path",
+ "type": "string"
+ },
"public_key": {
"type": "string"
},
@@ -5578,6 +6033,102 @@
},
"version": 0.1
},
+ "opentelemetry": {
+ "priority": 12009,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "properties": {
+ "additional_attributes": {
+ "items": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "disable": {
+ "type": "boolean"
+ },
+ "sampler": {
+ "default": {
+ "name": "always_off",
+ "options": {
+ "fraction": 0,
+ "root": {
+ "name": "always_off"
+ }
+ }
+ },
+ "properties": {
+ "name": {
+ "default": "always_off",
+ "enum": [
+ "always_off",
+ "always_on",
+ "parent_base",
+ "trace_id_ratio"
+ ],
+ "title": "sampling strategy",
+ "type": "string"
+ },
+ "options": {
+ "default": {
+ "fraction": 0,
+ "root": {
+ "name": "always_off"
+ }
+ },
+ "properties": {
+ "fraction": {
+ "default": 0,
+ "title": "trace_id_ratio fraction",
+ "type": "number"
+ },
+ "root": {
+ "default": {
+ "name": "always_off",
+ "options": {
+ "fraction": 0
+ }
+ },
+ "properties": {
+ "name": {
+ "default": "always_off",
+ "enum": [
+ "always_off",
+ "always_on",
+ "trace_id_ratio"
+ ],
+ "title": "sampling strategy",
+ "type": "string"
+ },
+ "options": {
+ "default": {
+ "fraction": 0
+ },
+ "properties": {
+ "fraction": {
+ "default": 0,
+ "title": "trace_id_ratio fraction parameter",
+ "type": "number"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "title": "parent_base root sampler",
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "version": 0.1
+ },
"openwhisk": {
"priority": -1901,
"schema": {
@@ -5793,7 +6344,11 @@
"type": "boolean"
},
"host": {
- "pattern": "^http(s)?:\\/\\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:[0-9]{1,5})?$",
+ "pattern": "^http(s)?:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?$",
+ "type": "string"
+ },
+ "path": {
+ "pattern": "^/[^?&]+$",
"type": "string"
},
"sample_ratio": {
@@ -5879,6 +6434,22 @@
},
"version": 0.1
},
+ "public-api": {
+ "priority": 501,
+ "schema": {
+ "$comment": "this is a mark for our injected plugin schema",
+ "properties": {
+ "disable": {
+ "type": "boolean"
+ },
+ "uri": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "version": 0.1
+ },
"real-ip": {
"priority": 23000,
"schema": {
@@ -6355,7 +6926,7 @@
"version": 0.1
},
"skywalking": {
- "priority": -1100,
+ "priority": 12010,
"schema": {
"$comment": "this is a mark for our injected plugin schema",
"properties": {
@@ -6647,7 +7218,6 @@
"type": "integer"
},
"max_retry_times": {
- "default": 1,
"minimum": 1,
"type": "integer"
},
@@ -6669,7 +7239,6 @@
"type": "integer"
},
"retry_interval": {
- "default": 1,
"minimum": 0,
"type": "integer"
},
@@ -7164,7 +7733,6 @@
},
"labels": {
"description": "key/value pairs to specify attributes",
- "maxProperties": 16,
"patternProperties": {
".*": {
"description": "value of label",
@@ -7525,7 +8093,7 @@
"version": 0.1
},
"zipkin": {
- "priority": 11011,
+ "priority": 12011,
"schema": {
"$comment": "this is a mark for our injected plugin schema",
"properties": {
diff --git a/api/internal/core/store/validate_test.go b/api/internal/core/store/validate_test.go
index c85e39a..6ea2466 100644
--- a/api/internal/core/store/validate_test.go
+++ b/api/internal/core/store/validate_test.go
@@ -82,8 +82,9 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
- }
+ "key": "remote_addr",
+ "policy": "local"
+ }
},
"desc": "test description"
}`
@@ -105,7 +106,8 @@
"limit-count": {
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"desc": "test description"
diff --git a/api/test/e2enew/consumer/consumer_test.go b/api/test/e2enew/consumer/consumer_test.go
index d420f88..0b25bcc 100644
--- a/api/test/e2enew/consumer/consumer_test.go
+++ b/api/test/e2enew/consumer/consumer_test.go
@@ -41,7 +41,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"desc": "test description"
@@ -69,7 +70,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 504,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"desc": "test description"
@@ -111,7 +113,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"desc": "test description"
diff --git a/api/test/e2enew/label/label_test.go b/api/test/e2enew/label/label_test.go
index 12f5900..954f72d 100644
--- a/api/test/e2enew/label/label_test.go
+++ b/api/test/e2enew/label/label_test.go
@@ -109,7 +109,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"upstream": {
diff --git a/api/test/e2enew/route/route_export_test.go b/api/test/e2enew/route/route_export_test.go
index 7e245df..de9923c 100644
--- a/api/test/e2enew/route/route_export_test.go
+++ b/api/test/e2enew/route/route_export_test.go
@@ -66,6 +66,7 @@
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -100,6 +101,7 @@
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -142,7 +144,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"status": 1,
@@ -195,6 +198,7 @@
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -229,6 +233,7 @@
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -272,7 +277,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"status": 1,
@@ -376,6 +382,7 @@
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -417,6 +424,7 @@
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -455,6 +463,7 @@
"limit-count": {
"count": 100,
"time_window": 60,
+ "policy": "local",
"rejected_code": 503,
"key": "remote_addr"
}
@@ -557,6 +566,7 @@
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -598,6 +608,7 @@
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
},
@@ -640,7 +651,8 @@
"count": 100,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"upstream": {
@@ -746,6 +758,7 @@
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -787,6 +800,7 @@
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
},
@@ -847,7 +861,8 @@
"count": 100,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"upstream_id": "1"
diff --git a/api/test/e2enew/route/route_with_plugin_limit_count_test.go b/api/test/e2enew/route/route_with_plugin_limit_count_test.go
index 45e384b..a25d15c 100644
--- a/api/test/e2enew/route/route_with_plugin_limit_count_test.go
+++ b/api/test/e2enew/route/route_with_plugin_limit_count_test.go
@@ -50,7 +50,8 @@
"count": 2,
"time_window": 2,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"upstream": {
@@ -137,7 +138,8 @@
"count": 2,
"time_window": 2,
"rejected_code": 503,
- "key": "consumer_name"
+ "key": "consumer_name",
+ "policy": "local"
}
},
"upstream": {
@@ -305,7 +307,8 @@
"time_window": 2,
"rejected_code": 503,
"key": "remote_addr",
- "disable": false
+ "disable": false,
+ "policy": "local"
}
},
"upstream": {
@@ -362,7 +365,8 @@
"time_window": 2,
"rejected_code": 503,
"key": "remote_addr",
- "disable": true
+ "disable": true,
+ "policy": "local"
}
},
"upstream": {
diff --git a/api/test/e2enew/schema/schema_test.go b/api/test/e2enew/schema/schema_test.go
index fb99b27..05127f4 100644
--- a/api/test/e2enew/schema/schema_test.go
+++ b/api/test/e2enew/schema/schema_test.go
@@ -45,7 +45,7 @@
Path: "/apisix/admin/schema/plugins/jwt-auth",
Headers: map[string]string{"Authorization": base.GetToken()},
ExpectStatus: http.StatusOK,
- ExpectBody: "{\"$comment\":\"this is a mark for our injected plugin schema\",\"properties\":{\"disable\":{\"type\":\"boolean\"}},\"type\":\"object\"}",
+ ExpectBody: `{"$comment":"this is a mark for our injected plugin schema","properties":{"cookie":{"default":"jwt","type":"string"},"disable":{"type":"boolean"},"header":{"default":"authorization","type":"string"},"query":{"default":"jwt","type":"string"}}`,
Sleep: base.SleepTime,
}),
table.Entry("get schema of non-existent plugin", base.HttpTestCase{
@@ -63,7 +63,7 @@
Path: "/apisix/admin/schemas/consumer",
Headers: map[string]string{"Authorization": base.GetToken()},
ExpectStatus: http.StatusOK,
- ExpectBody: `"properties":{"create_time":{"type":"integer"},"desc":{"maxLength":256,"type":"string"},"labels":{"description":"key/value pairs to specify attributes","maxProperties":16,"patternProperties":{".*":{"description":"value of label","maxLength":64,"minLength":1,"pattern":"^\\S+$","type":"string"}},"type":"object"},"plugins":{"type":"object"},"update_time":{"type":"integer"},"username":{"maxLength":100,"minLength":1,"pattern":"^[a-zA-Z0-9_]+$","type":"string"}}`,
+ ExpectBody: `"properties":{"create_time":{"type":"integer"},"desc":{"maxLength":256,"type":"string"},"labels":{"description":"key/value pairs to specify attributes","patternProperties":{".*":{"description":"value of label","maxLength":64,"minLength":1,"pattern":"^\\S+$","type":"string"}},"type":"object"},"plugins":{"type":"object"},"update_time":{"type":"integer"},"username":{"maxLength":100,"minLength":1,"pattern":"^[a-zA-Z0-9_]+$","type":"string"}}`,
Sleep: base.SleepTime,
}),
table.Entry("get schema of non-existent resources", base.HttpTestCase{
diff --git a/api/test/e2enew/service/service_test.go b/api/test/e2enew/service/service_test.go
index fde787b..39643d9 100644
--- a/api/test/e2enew/service/service_test.go
+++ b/api/test/e2enew/service/service_test.go
@@ -193,6 +193,7 @@
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
+ "policy": "local",
},
},
"upstream": map[string]interface{}{
@@ -225,7 +226,7 @@
Path: "/apisix/admin/services/s1",
Headers: map[string]string{"Authorization": base.GetToken()},
ExpectCode: http.StatusOK,
- ExpectBody: "\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"rejected_code\":503,\"time_window\":60}}",
+ ExpectBody: "\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"policy\":\"local\",\"rejected_code\":503,\"time_window\":60}}",
Sleep: base.SleepTime,
})
})
@@ -306,6 +307,7 @@
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
+ "policy": "local",
},
},
"upstream": map[string]interface{}{
@@ -341,7 +343,7 @@
Path: "/apisix/admin/services/s2",
Headers: map[string]string{"Authorization": base.GetToken()},
ExpectCode: http.StatusOK,
- ExpectBody: "\"name\":\"testservice22\",\"desc\":\"testservice_desc\",\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"rejected_code\":503,\"time_window\":60}},\"labels\":{\"build\":\"16\",\"env\":\"production\",\"version\":\"v2\"},\"enable_websocket\":true}",
+ ExpectBody: "\"name\":\"testservice22\",\"desc\":\"testservice_desc\",\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"policy\":\"local\",\"rejected_code\":503,\"time_window\":60}},\"labels\":{\"build\":\"16\",\"env\":\"production\",\"version\":\"v2\"},\"enable_websocket\":true}",
Sleep: base.SleepTime,
})
})
diff --git a/api/test/testdata/invalid-dag-conf.json b/api/test/testdata/invalid-dag-conf.json
index c11916a..260e06a 100644
--- a/api/test/testdata/invalid-dag-conf.json
+++ b/api/test/testdata/invalid-dag-conf.json
@@ -29,7 +29,8 @@
"count":2,
"time_window":60,
"rejected_code":503,
- "key":"remote_addr"
+ "key":"remote_addr",
+ "policy": "local"
}
},
"yy-uu-ii-oo":{
diff --git a/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md b/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
index 40d1e52..bd49c14 100644
--- a/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
+++ b/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
@@ -219,6 +219,7 @@
time_window: 60
rejected_code: 503
key: remote_addr
+ policy: local
responses:
'200':
description: list response
diff --git a/web/cypress/fixtures/plugin-dataset.json b/web/cypress/fixtures/plugin-dataset.json
index 6f02cde..f56bb37 100644
--- a/web/cypress/fixtures/plugin-dataset.json
+++ b/web/cypress/fixtures/plugin-dataset.json
@@ -593,7 +593,13 @@
"limit-count": [
{
"shouldValid": true,
- "data": { "count": 2, "time_window": 60, "rejected_code": 503, "key": "remote_addr" }
+ "data": {
+ "count": 2,
+ "time_window": 60,
+ "rejected_code": 503,
+ "key": "remote_addr",
+ "policy": "local"
+ }
},
{
"shouldValid": true,
@@ -601,14 +607,16 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "host"
+ "key": "host",
+ "policy": "local"
}
},
{
"shouldValid": false,
"data": {
"time_window": 60,
- "rejected_code": 503
+ "rejected_code": 503,
+ "policy": "local"
}
},
{
@@ -617,7 +625,8 @@
"count": -100,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
{
@@ -626,7 +635,8 @@
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "server_addr"
+ "key": "server_addr",
+ "policy": "local"
}
},
{
@@ -634,7 +644,8 @@
"data": {
"count": 2,
"time_window": 60,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
}
],
diff --git a/web/src/components/Plugin/PluginDetail.tsx b/web/src/components/Plugin/PluginDetail.tsx
index fde1626..4170a15 100644
--- a/web/src/components/Plugin/PluginDetail.tsx
+++ b/web/src/components/Plugin/PluginDetail.tsx
@@ -129,10 +129,16 @@
if (name === 'cors') {
const newMethods = formData.allow_methods.join(',');
- const compactAllowRegex = compact(formData.allow_origins_by_regex);
- // Note: default allow_origins_by_regex setted for UI is [''], but this is not allowed, omit it.
- if (compactAllowRegex.length === 0) {
- return omit({ ...formData, allow_methods: newMethods }, ['allow_origins_by_regex']);
+ const isFilterAllowRegex = compact(formData.allow_origins_by_regex).length === 0;
+ const isFilterAllowMetadata = compact(formData.allow_origins_by_metadata).length === 0;
+ // Note: default allow_origins_by_regex and allow_origins_by_metadata setted for UI is [''], but this is not allowed, omit it.
+ if (isFilterAllowRegex || isFilterAllowMetadata) {
+ const filterAllowRegex = (isFilterAllowRegex && 'allow_origins_by_regex') || '';
+ const filterAllowMetadata = (isFilterAllowMetadata && 'allow_origins_by_metadata') || '';
+ return omit({ ...formData, allow_methods: newMethods }, [
+ filterAllowRegex,
+ filterAllowMetadata,
+ ]);
}
return { ...formData, allow_methods: newMethods };
@@ -309,7 +315,10 @@
};
const isNoConfigurationRequired =
- pluginType === 'auth' && schemaType !== 'consumer' && monacoMode !== monacoModeList.UIForm && targetPluginName !== 'key-auth';
+ pluginType === 'auth' &&
+ schemaType !== 'consumer' &&
+ monacoMode !== monacoModeList.UIForm &&
+ targetPluginName !== 'key-auth';
return (
<Drawer
diff --git a/web/src/components/Plugin/UI/cors.tsx b/web/src/components/Plugin/UI/cors.tsx
index b639bb1..5c2bbd2 100644
--- a/web/src/components/Plugin/UI/cors.tsx
+++ b/web/src/components/Plugin/UI/cors.tsx
@@ -28,7 +28,7 @@
const FORM_ITEM_LAYOUT = {
labelCol: {
- span: 7,
+ span: 8,
},
wrapperCol: {
span: 8,
@@ -37,16 +37,20 @@
export const FORM_ITEM_WITHOUT_LABEL = {
wrapperCol: {
- sm: { span: 8, offset: 7 },
+ sm: { span: 8, offset: 8 },
},
};
const Cors: React.FC<Props> = ({ form, schema }) => {
const { formatMessage } = useIntl();
- const properties = schema?.properties
- const regexPro = properties.allow_origins_by_regex
- const { minLength, maxLength } = regexPro.items
- const regexInit = Array(regexPro.minItems).join('.').split('.')
+ const properties = schema?.properties;
+ const regexPro = properties.allow_origins_by_regex;
+ const metadataPro = properties.allow_origins_by_metadata;
+
+ const { minLength, maxLength } = regexPro.items;
+ const { minLength: metadataMinLength, maxLength: metadataMaxLength } = metadataPro.items;
+ const regexInit = Array(regexPro.minItems).join('.').split('.');
+ const metadataInit = Array(metadataPro.minItems).join('.').split('.');
const HTTPMethods: React.FC = () => (
<Form.Item
@@ -55,10 +59,7 @@
>
<Row>
<Col span={24}>
- <Form.Item
- name="allow_methods"
- initialValue={[properties.allow_methods.default]}
- >
+ <Form.Item name="allow_methods" initialValue={[properties.allow_methods.default]}>
<Select
mode="multiple"
optionLabelProp="label"
@@ -143,7 +144,53 @@
<Switch />
</Form.Item>
- <Form.List name='allow_origins_by_regex' initialValue={regexInit}>
+ <Form.List name="allow_origins_by_metadata" initialValue={metadataInit}>
+ {(fields, { add, remove }) => {
+ return (
+ <div>
+ {fields.map((field, index) => (
+ <Form.Item
+ {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
+ label={index === 0 && 'allow_origins_by_metadata'}
+ key={field.key}
+ tooltip={formatMessage({
+ id: 'component.pluginForm.cors.allow_origins_by_metadata.tooltip',
+ })}
+ >
+ <Form.Item {...field} validateTrigger={['onChange', 'onBlur']} noStyle>
+ <Input style={{ width: '80%' }} />
+ </Form.Item>
+ {fields.length > metadataMinLength && (
+ <MinusCircleOutlined
+ className="dynamic-delete-button"
+ style={{ margin: '0 8px' }}
+ onClick={() => {
+ remove(field.name);
+ }}
+ />
+ )}
+ </Form.Item>
+ ))}
+ {
+ <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
+ {fields.length < metadataMaxLength && (
+ <Button
+ type="dashed"
+ onClick={() => {
+ add();
+ }}
+ >
+ <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
+ </Button>
+ )}
+ </Form.Item>
+ }
+ </div>
+ );
+ }}
+ </Form.List>
+
+ <Form.List name="allow_origins_by_regex" initialValue={regexInit}>
{(fields, { add, remove }) => {
return (
<div>
@@ -159,7 +206,7 @@
<Form.Item {...field} validateTrigger={['onChange', 'onBlur']} noStyle>
<Input style={{ width: '80%' }} />
</Form.Item>
- {fields.length > minLength &&
+ {fields.length > minLength && (
<MinusCircleOutlined
className="dynamic-delete-button"
style={{ margin: '0 8px' }}
@@ -167,20 +214,22 @@
remove(field.name);
}}
/>
- }
+ )}
</Form.Item>
))}
{
<Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
- {fields.length < maxLength && <Button
- type="dashed"
- data-cy="add-allow_origins_by_regex"
- onClick={() => {
- add();
- }}
- >
- <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
- </Button>}
+ {fields.length < maxLength && (
+ <Button
+ type="dashed"
+ data-cy="add-allow_origins_by_regex"
+ onClick={() => {
+ add();
+ }}
+ >
+ <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
+ </Button>
+ )}
</Form.Item>
}
</div>
diff --git a/web/src/components/Plugin/UI/limit-count.tsx b/web/src/components/Plugin/UI/limit-count.tsx
index 15eb595..29c359e 100644
--- a/web/src/components/Plugin/UI/limit-count.tsx
+++ b/web/src/components/Plugin/UI/limit-count.tsx
@@ -239,7 +239,8 @@
const properties = schema?.properties;
const [policy, setPoicy] = useState<PolicyProps>(properties.policy.default);
const { formatMessage } = useIntl();
- const dependSchema = schema?.dependencies.policy.oneOf;
+ const redisSchema = schema?.then;
+ const redisClusterSchema = schema?.else.then;
return (
<Form form={form} {...FORM_ITEM_LAYOUT}>
@@ -367,8 +368,8 @@
setPoicy(form.getFieldValue('policy'));
}}
</Form.Item>
- {Boolean(policy === 'redis') && <RedisForm schema={dependSchema[1]} />}
- {Boolean(policy === 'redis-cluster') && <RedisClusterForm schema={dependSchema[2]} />}
+ {Boolean(policy === 'redis') && <RedisForm schema={redisSchema} />}
+ {Boolean(policy === 'redis-cluster') && <RedisClusterForm schema={redisClusterSchema} />}
</Form>
);
};
diff --git a/web/src/components/Plugin/UI/proxy-mirror.tsx b/web/src/components/Plugin/UI/proxy-mirror.tsx
index 5b19cab..4fca5a0 100644
--- a/web/src/components/Plugin/UI/proxy-mirror.tsx
+++ b/web/src/components/Plugin/UI/proxy-mirror.tsx
@@ -26,7 +26,7 @@
const FORM_ITEM_LAYOUT = {
labelCol: {
- span: 4,
+ span: 6,
},
wrapperCol: {
span: 10,
@@ -42,15 +42,30 @@
<Form.Item
label="host"
name="host"
+ required
extra={formatMessage({ id: 'component.pluginForm.proxy-mirror.host.extra' })}
tooltip={formatMessage({ id: 'component.pluginForm.proxy-mirror.host.tooltip' })}
rules={[
{
+ required: true,
pattern: new RegExp(`${properties.host.pattern}`, 'g'),
message: formatMessage({ id: 'component.pluginForm.proxy-mirror.host.ruletip' }),
},
]}
>
+ <Input required />
+ </Form.Item>
+ <Form.Item
+ label="path"
+ name="path"
+ tooltip={formatMessage({ id: 'component.pluginForm.proxy-mirror.path.tooltip' })}
+ rules={[
+ {
+ pattern: new RegExp(`${properties.path.pattern}`, 'g'),
+ message: formatMessage({ id: 'component.pluginForm.proxy-mirror.path.ruletip' }),
+ },
+ ]}
+ >
<Input />
</Form.Item>
<Form.Item
diff --git a/web/src/components/Plugin/data.tsx b/web/src/components/Plugin/data.tsx
index 0f40f04..7b1d499 100644
--- a/web/src/components/Plugin/data.tsx
+++ b/web/src/components/Plugin/data.tsx
@@ -269,4 +269,43 @@
'aws-lambda': {
type: PluginType.serverless,
},
+ 'clickhouse-logger': {
+ type: PluginType.observability,
+ },
+ 'client-control': {
+ type: PluginType.traffic,
+ },
+ csrf: {
+ type: PluginType.security,
+ },
+ 'ext-plugin-post-req': {
+ type: PluginType.other,
+ },
+ 'ext-plugin-pre-req': {
+ type: PluginType.other,
+ },
+ 'file-logger': {
+ type: PluginType.observability,
+ },
+ gzip: {
+ type: PluginType.other,
+ },
+ loggly: {
+ type: PluginType.observability,
+ },
+ 'public-api': {
+ type: PluginType.security,
+ },
+ 'real-ip': {
+ type: PluginType.other,
+ },
+ 'authz-casdoor': {
+ type: PluginType.authentication,
+ },
+ mocking: {
+ type: PluginType.other,
+ },
+ opentelemetry: {
+ type: PluginType.observability,
+ },
};
diff --git a/web/src/components/Plugin/locales/en-US.ts b/web/src/components/Plugin/locales/en-US.ts
index f87b8da..b7d6a70 100644
--- a/web/src/components/Plugin/locales/en-US.ts
+++ b/web/src/components/Plugin/locales/en-US.ts
@@ -46,6 +46,8 @@
'Maximum number of seconds the results can be cached. Within this time range, the browser will reuse the last check result. -1 means no cache. Please note that the maximum value is depended on browser, please refer to MDN for details.',
'component.pluginForm.cors.allow_credential.tooltip':
"If you set this option to true, you can not use '*' for other options.",
+ 'component.pluginForm.cors.allow_origins_by_metadata.tooltip':
+ 'Match which origin is allowed to enable CORS by referencing allow_origins set in plugin metadata.',
'component.pluginForm.cors.allow_origins_by_regex.tooltip':
'Use regex expressions to match which origin is allowed to enable CORS, for example, [".*.test.com"] can use to match all subdomain of test.com.',
@@ -78,6 +80,9 @@
'component.pluginForm.proxy-mirror.host.extra': 'e.g. http://127.0.0.1:9797',
'component.pluginForm.proxy-mirror.host.ruletip':
'address needs to contain schema: http or https, not URI part',
+ 'component.pluginForm.proxy-mirror.path.tooltip':
+ "Specify the mirror request's path part. Without it the current path will be used.",
+ 'component.pluginForm.proxy-mirror.path.ruletip': 'Please enter the correct path, e.g. /path',
'component.pluginForm.proxy-mirror.sample_ratio.tooltip':
'the sample ratio that requests will be mirrored.',
diff --git a/web/src/components/Plugin/locales/zh-CN.ts b/web/src/components/Plugin/locales/zh-CN.ts
index 41ed113..6368d16 100644
--- a/web/src/components/Plugin/locales/zh-CN.ts
+++ b/web/src/components/Plugin/locales/zh-CN.ts
@@ -45,6 +45,8 @@
'浏览器缓存 CORS 结果的最大时间,单位为秒,在这个时间范围内浏览器会复用上一次的检查结果,-1 表示不缓存。',
'component.pluginForm.cors.allow_credential.tooltip':
'是否允许跨域访问的请求方携带凭据(如 Cookie 等)。根据 CORS 规范,如果设置该选项为 true,那么将不能在其他选项中使用 * 。',
+ 'component.pluginForm.cors.allow_origins_by_metadata.tooltip':
+ '通过引用插件元数据的 allow_origins 配置允许跨域访问的 Origin。',
'component.pluginForm.cors.allow_origins_by_regex.tooltip':
'使用正则表达式数组来匹配允许跨域访问的 Origin, 如[".*.test.com"] 可以匹配任何test.com的子域名 * 。',
@@ -73,6 +75,9 @@
'component.pluginForm.proxy-mirror.host.extra': '例如:http://127.0.0.1:9797',
'component.pluginForm.proxy-mirror.host.ruletip':
'地址中需要包含 schema :http或https,不能包含 URI 部分',
+ 'component.pluginForm.proxy-mirror.path.tooltip':
+ '指定镜像请求的路径。如不指定,当前路径将被使用。',
+ 'component.pluginForm.proxy-mirror.path.ruletip': '请输入正确的路径,例如: /path',
'component.pluginForm.proxy-mirror.sample_ratio.tooltip': '镜像请求采样率',
// limit-conn
diff --git a/web/src/components/Upstream/components/ServiceDiscovery.tsx b/web/src/components/Upstream/components/ServiceDiscovery.tsx
index deda648..cbd6eb4 100644
--- a/web/src/components/Upstream/components/ServiceDiscovery.tsx
+++ b/web/src/components/Upstream/components/ServiceDiscovery.tsx
@@ -32,6 +32,7 @@
args: ['group_name', 'namespace_id'],
},
eureka: {},
+ kubernetes: {},
};
const ServiceDiscovery: React.FC<Props> = ({ readonly, form }) => {
diff --git a/web/src/components/Upstream/locales/en-US.ts b/web/src/components/Upstream/locales/en-US.ts
index 0d82232..b1ba0fe 100644
--- a/web/src/components/Upstream/locales/en-US.ts
+++ b/web/src/components/Upstream/locales/en-US.ts
@@ -31,6 +31,7 @@
'component.upstream.fields.discovery_type.type.consul_kv': 'Consul KV',
'component.upstream.fields.discovery_type.type.nacos': 'Nacos',
'component.upstream.fields.discovery_type.type.eureka': 'Eureka',
+ 'component.upstream.fields.discovery_type.type.kubernetes': 'Kubernetes',
'component.upstream.fields.discovery_args.group_name': 'Group Name',
'component.upstream.fields.discovery_args.group_name.tooltip': 'Group Name',
diff --git a/web/src/components/Upstream/locales/zh-CN.ts b/web/src/components/Upstream/locales/zh-CN.ts
index 4e1dc10..5de7c6e 100644
--- a/web/src/components/Upstream/locales/zh-CN.ts
+++ b/web/src/components/Upstream/locales/zh-CN.ts
@@ -31,6 +31,7 @@
'component.upstream.fields.discovery_type.type.consul_kv': 'Consul KV',
'component.upstream.fields.discovery_type.type.nacos': 'Nacos',
'component.upstream.fields.discovery_type.type.eureka': 'Eureka',
+ 'component.upstream.fields.discovery_type.type.kubernetes': 'Kubernetes',
'component.upstream.fields.discovery_args.group_name': '分组名',
'component.upstream.fields.discovery_args.group_name.tooltip': '分组名',