This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 5a630b878 feat: support multiple kubernets clusters discovery (#7895)
5a630b878 is described below
commit 5a630b878e01c1fc9efdfe3661141658e4f3dc42
Author: zhixiongdu <[email protected]>
AuthorDate: Thu Sep 15 11:25:37 2022 +0800
feat: support multiple kubernets clusters discovery (#7895)
---
.github/workflows/kubernetes-ci.yml | 19 +-
apisix/cli/ngx_tpl.lua | 7 +-
apisix/cli/ops.lua | 57 +-
apisix/discovery/kubernetes/init.lua | 277 ++++++--
apisix/discovery/kubernetes/schema.lua | 254 ++++---
t/APISIX.pm | 2 +
t/cli/test_kubernetes.sh | 81 ++-
t/kubernetes/discovery/kubernetes.t | 751 +++++----------------
.../discovery/{kubernetes.t => kubernetes2.t} | 411 +++++------
.../discovery/{kubernetes.t => kubernetes3.t} | 411 +++++------
10 files changed, 1082 insertions(+), 1188 deletions(-)
diff --git a/.github/workflows/kubernetes-ci.yml
b/.github/workflows/kubernetes-ci.yml
index 9800e681f..b6495d765 100644
--- a/.github/workflows/kubernetes-ci.yml
+++ b/.github/workflows/kubernetes-ci.yml
@@ -44,22 +44,17 @@ jobs:
- name: Setup kubernetes cluster
run: |
- KIND_VERSION="v0.11.1"
- KUBECTL_VERSION="v1.22.0"
- curl -Lo ./kind
"https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-$(uname)-amd64"
- curl -Lo ./kubectl
"https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl"
- chmod +x ./kind
- chmod +x ./kubectl
+ KUBERNETES_VERSION="v1.22.7"
- ./kind create cluster --name apisix-test --config
./t/kubernetes/configs/kind.yaml
+ kind create cluster --name apisix-test --config
./t/kubernetes/configs/kind.yaml --image kindest/node:${KUBERNETES_VERSION}
- ./kubectl wait --for=condition=Ready nodes --all --timeout=180s
+ kubectl wait --for=condition=Ready nodes --all --timeout=180s
- ./kubectl apply -f ./t/kubernetes/configs/account.yaml
+ kubectl apply -f ./t/kubernetes/configs/account.yaml
- ./kubectl apply -f ./t/kubernetes/configs/endpoint.yaml
+ kubectl apply -f ./t/kubernetes/configs/endpoint.yaml
- KUBERNETES_CLIENT_TOKEN_CONTENT=$(./kubectl get secrets | grep
apisix-test | awk '{system("./kubectl get secret -o jsonpath={.data.token} "$1"
| base64 --decode")}')
+ KUBERNETES_CLIENT_TOKEN_CONTENT=$(kubectl get secrets | grep
apisix-test | awk '{system("kubectl get secret -o jsonpath={.data.token} "$1" |
base64 --decode")}')
KUBERNETES_CLIENT_TOKEN_DIR="/tmp/var/run/secrets/kubernetes.io/serviceaccount"
@@ -73,7 +68,7 @@ jobs:
echo 'KUBERNETES_CLIENT_TOKEN='"${KUBERNETES_CLIENT_TOKEN_CONTENT}"
echo 'KUBERNETES_CLIENT_TOKEN_FILE='${KUBERNETES_CLIENT_TOKEN_FILE}
- ./kubectl proxy -p 6445 &
+ kubectl proxy -p 6445 &
- name: Linux Install
run: |
diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua
index 5d814a091..4d1bc5a6b 100644
--- a/apisix/cli/ngx_tpl.lua
+++ b/apisix/cli/ngx_tpl.lua
@@ -238,8 +238,11 @@ http {
lua_shared_dict balancer-ewma-last-touched-at {*
http.lua_shared_dict["balancer-ewma-last-touched-at"] *};
lua_shared_dict etcd-cluster-health-check {*
http.lua_shared_dict["etcd-cluster-health-check"] *}; # etcd health check
- {% if enabled_discoveries["kubernetes"] then %}
- lua_shared_dict kubernetes {* http.lua_shared_dict["kubernetes"] *};
+ # for discovery shared dict
+ {% if discovery_shared_dicts then %}
+ {% for key, size in pairs(discovery_shared_dicts) do %}
+ lua_shared_dict {*key*} {*size*};
+ {% end %}
{% end %}
{% if enabled_discoveries["tars"] then %}
diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua
index a362d111c..d00ce072d 100644
--- a/apisix/cli/ops.lua
+++ b/apisix/cli/ops.lua
@@ -662,36 +662,52 @@ Please modify "admin_key" in conf/config.yaml .
end
end
- -- inject kubernetes discovery environment variable
+ -- inject kubernetes discovery shared dict and environment variable
if enabled_discoveries["kubernetes"] then
- local kubernetes_conf = yaml_conf.discovery["kubernetes"]
+ if not sys_conf["discovery_shared_dicts"] then
+ sys_conf["discovery_shared_dicts"] = {}
+ end
- local keys = {
- kubernetes_conf.service.host,
- kubernetes_conf.service.port,
- }
+ local kubernetes_conf = yaml_conf.discovery["kubernetes"]
- if kubernetes_conf.client.token then
- table_insert(keys, kubernetes_conf.client.token)
- end
+ local inject_environment = function(conf, envs)
+ local keys = {
+ conf.service.host,
+ conf.service.port,
+ }
- if kubernetes_conf.client.token_file then
- table_insert(keys, kubernetes_conf.client.token_file)
- end
+ if conf.client.token then
+ table_insert(keys, conf.client.token)
+ end
- local envs = {}
+ if conf.client.token_file then
+ table_insert(keys, conf.client.token_file)
+ end
- for _, key in ipairs(keys) do
- if #key > 3 then
- local first, second = str_byte(key, 1, 2)
- if first == str_byte('$') and second == str_byte('{') then
- local last = str_byte(key, #key)
- if last == str_byte('}') then
- envs[str_sub(key, 3, #key - 1)] = ""
+ for _, key in ipairs(keys) do
+ if #key > 3 then
+ local first, second = str_byte(key, 1, 2)
+ if first == str_byte('$') and second == str_byte('{') then
+ local last = str_byte(key, #key)
+ if last == str_byte('}') then
+ envs[str_sub(key, 3, #key - 1)] = ""
+ end
end
end
end
+
+ end
+
+ local envs = {}
+ if #kubernetes_conf == 0 then
+ sys_conf["discovery_shared_dicts"]["kubernetes"] =
kubernetes_conf.shared_size
+ inject_environment(kubernetes_conf, envs)
+ else
+ for _, item in ipairs(kubernetes_conf) do
+ sys_conf["discovery_shared_dicts"]["kubernetes-" .. item.id] =
item.shared_size
+ inject_environment(item, envs)
+ end
end
if not sys_conf["envs"] then
@@ -701,6 +717,7 @@ Please modify "admin_key" in conf/config.yaml .
for item in pairs(envs) do
table_insert(sys_conf["envs"], item)
end
+
end
-- fix up lua path
diff --git a/apisix/discovery/kubernetes/init.lua
b/apisix/discovery/kubernetes/init.lua
index a0491be45..d7258a556 100644
--- a/apisix/discovery/kubernetes/init.lua
+++ b/apisix/discovery/kubernetes/init.lua
@@ -24,15 +24,15 @@ local tostring = tostring
local os = os
local error = error
local pcall = pcall
+local setmetatable = setmetatable
local process = require("ngx.process")
local core = require("apisix.core")
local util = require("apisix.cli.util")
local local_conf = require("apisix.core.config_local").local_conf()
local informer_factory =
require("apisix.discovery.kubernetes.informer_factory")
-local endpoint_dict
-local default_weight
+local ctx
local endpoint_lrucache = core.lrucache.new({
ttl = 300,
@@ -50,9 +50,9 @@ local function sort_nodes_cmp(left, right)
end
-local function on_endpoint_modified(informer, endpoint)
- if informer.namespace_selector and
- not informer:namespace_selector(endpoint.metadata.namespace) then
+local function on_endpoint_modified(handle, endpoint)
+ if handle.namespace_selector and
+ not handle:namespace_selector(endpoint.metadata.namespace) then
return
end
@@ -83,7 +83,7 @@ local function on_endpoint_modified(informer, endpoint)
core.table.insert(nodes, {
host = address.ip,
port = port.port,
- weight = default_weight
+ weight = handle.default_weight
})
end
end
@@ -101,39 +101,39 @@ local function on_endpoint_modified(informer, endpoint)
local endpoint_version = ngx.crc32_long(endpoint_content)
local _, err
- _, err = endpoint_dict:safe_set(endpoint_key .. "#version",
endpoint_version)
+ _, err = handle.endpoint_dict:safe_set(endpoint_key .. "#version",
endpoint_version)
if err then
core.log.error("set endpoint version into discovery DICT failed, ",
err)
return
end
- _, err = endpoint_dict:safe_set(endpoint_key, endpoint_content)
+ _, err = handle.endpoint_dict:safe_set(endpoint_key, endpoint_content)
if err then
core.log.error("set endpoint into discovery DICT failed, ", err)
- endpoint_dict:delete(endpoint_key .. "#version")
+ handle.endpoint_dict:delete(endpoint_key .. "#version")
end
end
-local function on_endpoint_deleted(informer, endpoint)
- if informer.namespace_selector and
- not informer:namespace_selector(endpoint.metadata.namespace) then
+local function on_endpoint_deleted(handle, endpoint)
+ if handle.namespace_selector and
+ not handle:namespace_selector(endpoint.metadata.namespace) then
return
end
core.log.debug(core.json.delay_encode(endpoint))
local endpoint_key = endpoint.metadata.namespace .. "/" ..
endpoint.metadata.name
- endpoint_dict:delete(endpoint_key .. "#version")
- endpoint_dict:delete(endpoint_key)
+ handle.endpoint_dict:delete(endpoint_key .. "#version")
+ handle.endpoint_dict:delete(endpoint_key)
end
-local function pre_list(informer)
- endpoint_dict:flush_all()
+local function pre_list(handle)
+ handle.endpoint_dict:flush_all()
end
-local function post_list(informer)
- endpoint_dict:flush_expired()
+local function post_list(handle)
+ handle.endpoint_dict:flush_expired()
end
@@ -184,7 +184,7 @@ local function setup_namespace_selector(conf, informer)
local not_match = conf.namespace_selector.not_match
local m, err
for _, v in ipairs(not_match) do
- m, err = ngx.re.match(namespace, v, "j")
+ m, err = ngx.re.match(namespace, v, "jo")
if m and m[0] == namespace then
return false
end
@@ -196,24 +196,26 @@ local function setup_namespace_selector(conf, informer)
end
return
end
+
+ return
end
local function read_env(key)
if #key > 3 then
- local a, b = string.byte(key, 1, 2)
- local c = string.byte(key, #key, #key)
- -- '$', '{', '}' == 36,123,125
- if a == 36 and b == 123 and c == 125 then
- local env = string.sub(key, 3, #key - 1)
- local value = os.getenv(env)
- if not value then
- return nil, "not found environment variable " .. env
+ local first, second = string.byte(key, 1, 2)
+ if first == string.byte('$') and second == string.byte('{') then
+ local last = string.byte(key, #key)
+ if last == string.byte('}') then
+ local env = string.sub(key, 3, #key - 1)
+ local value = os.getenv(env)
+ if not value then
+ return nil, "not found environment variable " .. env
+ end
+ return value
end
- return value, nil
end
end
-
return key
end
@@ -272,6 +274,9 @@ local function get_apiserver(conf)
return nil, "one of [client.token,client.token_file] should be set but
none"
end
+ -- remove possible extra whitespace
+ apiserver.token = apiserver.token:gsub("%s+", "")
+
if apiserver.schema == "https" and apiserver.token == "" then
return nil, "apiserver.token should set to non-empty string when
service.schema is https"
end
@@ -279,8 +284,7 @@ local function get_apiserver(conf)
return apiserver
end
-
-local function create_endpoint_lrucache(endpoint_key, endpoint_port)
+local function create_endpoint_lrucache(endpoint_dict, endpoint_key,
endpoint_port)
local endpoint_content = endpoint_dict:get_stale(endpoint_key)
if not endpoint_content then
core.log.error("get empty endpoint content from discovery DIC, this
should not happen ",
@@ -298,60 +302,64 @@ local function create_endpoint_lrucache(endpoint_key,
endpoint_port)
return endpoint[endpoint_port]
end
+
local _M = {
version = "0.0.1"
}
-function _M.nodes(service_name)
- local pattern = "^(.*):(.*)$" -- namespace/name:port_name
- local match = ngx.re.match(service_name, pattern, "jo")
- if not match then
- core.log.info("get unexpected upstream service_name: ", service_name)
- return nil
- end
- local endpoint_key = match[1]
- local endpoint_port = match[2]
- local endpoint_version = endpoint_dict:get_stale(endpoint_key ..
"#version")
- if not endpoint_version then
- core.log.info("get empty endpoint version from discovery DICT ",
endpoint_key)
- return nil
- end
+local function start_fetch(handle)
+ local timer_runner
+ timer_runner = function(premature)
+ if premature then
+ return
+ end
- return endpoint_lrucache(service_name, endpoint_version,
- create_endpoint_lrucache, endpoint_key, endpoint_port)
+ local ok, status = pcall(handle.list_watch, handle, handle.apiserver)
+
+ local retry_interval = 0
+ if not ok then
+ core.log.error("list_watch failed, kind: ", handle.kind,
+ ", reason: ", "RuntimeException", ", message : ", status)
+ retry_interval = 40
+ elseif not status then
+ retry_interval = 40
+ end
+
+ ngx.timer.at(retry_interval, timer_runner)
+ end
+ ngx.timer.at(0, timer_runner)
end
-function _M.init_worker()
- endpoint_dict = ngx.shared.kubernetes
+local function single_mode_init(conf)
+ local endpoint_dict = ngx.shared.kubernetes
if not endpoint_dict then
- error("failed to get lua_shared_dict: kubernetes, please check your
APISIX version")
+ error("failed to get lua_shared_dict: ngx.shared.kubernetes, " ..
+ "please check your APISIX version")
end
if process.type() ~= "privileged agent" then
+ ctx = endpoint_dict
return
end
- local discovery_conf = local_conf.discovery.kubernetes
-
- default_weight = discovery_conf.default_weight
-
- local apiserver, err = get_apiserver(discovery_conf)
+ local apiserver, err = get_apiserver(conf)
if err then
error(err)
return
end
- local endpoints_informer, err = informer_factory.new("", "v1",
- "Endpoints", "endpoints", "")
+ local default_weight = conf.default_weight
+
+ local endpoints_informer, err = informer_factory.new("", "v1",
"Endpoints", "endpoints", "")
if err then
error(err)
return
end
- setup_namespace_selector(discovery_conf, endpoints_informer)
- setup_label_selector(discovery_conf, endpoints_informer)
+ setup_namespace_selector(conf, endpoints_informer)
+ setup_label_selector(conf, endpoints_informer)
endpoints_informer.on_added = on_endpoint_modified
endpoints_informer.on_modified = on_endpoint_modified
@@ -359,27 +367,152 @@ function _M.init_worker()
endpoints_informer.pre_list = pre_list
endpoints_informer.post_list = post_list
- local timer_runner
- timer_runner = function(premature)
- if premature then
+ ctx = setmetatable({
+ endpoint_dict = endpoint_dict,
+ apiserver = apiserver,
+ default_weight = default_weight
+ }, { __index = endpoints_informer })
+
+ start_fetch(ctx)
+end
+
+
+local function single_mode_nodes(service_name)
+ local pattern = "^(.*):(.*)$" -- namespace/name:port_name
+ local match = ngx.re.match(service_name, pattern, "jo")
+ if not match then
+ core.log.error("get unexpected upstream service_name: ", service_name)
+ return nil
+ end
+
+ local endpoint_dict = ctx
+ local endpoint_key = match[1]
+ local endpoint_port = match[2]
+ local endpoint_version = endpoint_dict:get_stale(endpoint_key ..
"#version")
+ if not endpoint_version then
+ core.log.info("get empty endpoint version from discovery DICT ",
endpoint_key)
+ return nil
+ end
+
+ return endpoint_lrucache(service_name, endpoint_version,
+ create_endpoint_lrucache, endpoint_dict, endpoint_key,
endpoint_port)
+end
+
+
+local function multiple_mode_worker_init(confs)
+ for _, conf in ipairs(confs) do
+
+ local id = conf.id
+ if ctx[id] then
+ error("duplicate id value")
+ end
+
+ local endpoint_dict = ngx.shared["kubernetes-" .. id]
+ if not endpoint_dict then
+ error(string.format("failed to get lua_shared_dict:
ngx.shared.kubernetes-%s, ", id) ..
+ "please check your APISIX version")
+ end
+
+ ctx[id] = endpoint_dict
+ end
+end
+
+
+local function multiple_mode_init(confs)
+ ctx = core.table.new(#confs, 0)
+
+ if process.type() ~= "privileged agent" then
+ multiple_mode_worker_init(confs)
+ return
+ end
+
+ for _, conf in ipairs(confs) do
+ local id = conf.id
+
+ if ctx[id] then
+ error("duplicate id value")
+ end
+
+ local endpoint_dict = ngx.shared["kubernetes-" .. id]
+ if not endpoint_dict then
+ error(string.format("failed to get lua_shared_dict:
ngx.shared.kubernetes-%s, ", id) ..
+ "please check your APISIX version")
+ end
+
+ local apiserver, err = get_apiserver(conf)
+ if err then
+ error(err)
return
end
- local ok, status = pcall(endpoints_informer.list_watch,
endpoints_informer, apiserver)
+ local default_weight = conf.default_weight
- local retry_interval = 0
- if not ok then
- core.log.error("list_watch failed, kind: ",
endpoints_informer.kind,
- ", reason: ", "RuntimeException", ", message : ", status)
- retry_interval = 40
- elseif not status then
- retry_interval = 40
+ local endpoints_informer, err = informer_factory.new("", "v1",
"Endpoints", "endpoints", "")
+ if err then
+ error(err)
+ return
end
- ngx.timer.at(retry_interval, timer_runner)
+ setup_namespace_selector(conf, endpoints_informer)
+ setup_label_selector(conf, endpoints_informer)
+
+ endpoints_informer.on_added = on_endpoint_modified
+ endpoints_informer.on_modified = on_endpoint_modified
+ endpoints_informer.on_deleted = on_endpoint_deleted
+ endpoints_informer.pre_list = pre_list
+ endpoints_informer.post_list = post_list
+
+ ctx[id] = setmetatable({
+ endpoint_dict = endpoint_dict,
+ apiserver = apiserver,
+ default_weight = default_weight
+ }, { __index = endpoints_informer })
end
- ngx.timer.at(0, timer_runner)
+ for _, item in pairs(ctx) do
+ start_fetch(item)
+ end
+end
+
+
+local function multiple_mode_nodes(service_name)
+ local pattern = "^(.*)/(.*/.*):(.*)$" -- id/namespace/name:port_name
+ local match = ngx.re.match(service_name, pattern, "jo")
+ if not match then
+ core.log.error("get unexpected upstream service_name: ", service_name)
+ return nil
+ end
+
+ local id = match[1]
+ local endpoint_dict = ctx[id]
+ if not endpoint_dict then
+ core.log.error("id not exist")
+ return nil
+ end
+
+ local endpoint_key = match[2]
+ local endpoint_port = match[3]
+ local endpoint_version = endpoint_dict:get_stale(endpoint_key ..
"#version")
+ if not endpoint_version then
+ core.log.info("get empty endpoint version from discovery DICT ",
endpoint_key)
+ return nil
+ end
+
+ return endpoint_lrucache(service_name, endpoint_version,
+ create_endpoint_lrucache, endpoint_dict, endpoint_key,
endpoint_port)
+end
+
+
+function _M.init_worker()
+ local discovery_conf = local_conf.discovery.kubernetes
+ core.log.info("kubernetes discovery conf: ",
core.json.delay_encode(discovery_conf))
+ if #discovery_conf == 0 then
+ _M.nodes = single_mode_nodes
+ single_mode_init(discovery_conf)
+ else
+ _M.nodes = multiple_mode_nodes
+ multiple_mode_init(discovery_conf)
+ end
end
return _M
diff --git a/apisix/discovery/kubernetes/schema.lua
b/apisix/discovery/kubernetes/schema.lua
index 4888de63c..170608f55 100644
--- a/apisix/discovery/kubernetes/schema.lua
+++ b/apisix/discovery/kubernetes/schema.lua
@@ -25,116 +25,186 @@ local port_patterns = {
{ pattern =
[[^(([1-9]\d{0,3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5]))$]]
},
}
+local schema_schema = {
+ type = "string",
+ enum = { "http", "https" },
+ default = "https",
+}
+
+local token_patterns = {
+ { pattern = [[\${[_A-Za-z]([_A-Za-z0-9]*[_A-Za-z])*}$]] },
+ { pattern = [[^[A-Za-z0-9+\/._=-]{0,4096}$]] },
+}
+
+local token_schema = {
+ type = "string",
+ oneOf = token_patterns,
+}
+
+local token_file_schema = {
+ type = "string",
+ pattern = [[^[^\:*?"<>|]*$]],
+ minLength = 1,
+ maxLength = 500,
+}
+
local namespace_pattern = [[^[a-z0-9]([-a-z0-9_.]*[a-z0-9])?$]]
+
local namespace_regex_pattern = [[^[\x21-\x7e]*$]]
-return {
+local namespace_selector_schema = {
type = "object",
properties = {
- service = {
- type = "object",
- properties = {
- schema = {
- type = "string",
- enum = { "http", "https" },
- default = "https",
- },
- host = {
- type = "string",
- default = "${KUBERNETES_SERVICE_HOST}",
- oneOf = host_patterns,
- },
- port = {
- type = "string",
- default = "${KUBERNETES_SERVICE_PORT}",
- oneOf = port_patterns,
- },
- },
- default = {
- schema = "https",
- host = "${KUBERNETES_SERVICE_HOST}",
- port = "${KUBERNETES_SERVICE_PORT}",
- }
+ equal = {
+ type = "string",
+ pattern = namespace_pattern,
},
- client = {
- type = "object",
- properties = {
- token = {
- type = "string",
- oneOf = {
- { pattern =
[[\${[_A-Za-z]([_A-Za-z0-9]*[_A-Za-z])*}$]] },
- { pattern = [[^[A-Za-z0-9+\/._=-]{0,4096}$]] },
- },
- },
- token_file = {
- type = "string",
- pattern = [[^[^\:*?"<>|]*$]],
- minLength = 1,
- maxLength = 500,
- }
- },
- oneOf = {
- { required = { "token" } },
- { required = { "token_file" } },
+ not_equal = {
+ type = "string",
+ pattern = namespace_pattern,
+ },
+ match = {
+ type = "array",
+ items = {
+ type = "string",
+ pattern = namespace_regex_pattern
},
- default = {
- token_file =
"/var/run/secrets/kubernetes.io/serviceaccount/token"
- }
+ minItems = 1
},
- default_weight = {
- type = "integer",
- default = 50,
- minimum = 0,
+ not_match = {
+ type = "array",
+ items = {
+ type = "string",
+ pattern = namespace_regex_pattern
+ },
+ minItems = 1
},
- namespace_selector = {
+ },
+ oneOf = {
+ { required = {} },
+ { required = { "equal" } },
+ { required = { "not_equal" } },
+ { required = { "match" } },
+ { required = { "not_match" } }
+ },
+}
+
+local label_selector_schema = {
+ type = "string",
+}
+
+local default_weight_schema = {
+ type = "integer",
+ default = 50,
+ minimum = 0,
+}
+
+local shared_size_schema = {
+ type = "string",
+ pattern = [[^[1-9][0-9]?m$]],
+ default = "1m",
+}
+
+return {
+ anyOf = {
+ {
type = "object",
properties = {
- equal = {
- type = "string",
- pattern = namespace_pattern,
- },
- not_equal = {
- type = "string",
- pattern = namespace_pattern,
+ service = {
+ type = "object",
+ properties = {
+ schema = schema_schema,
+ host = {
+ type = "string",
+ oneOf = host_patterns,
+ default = "${KUBERNETES_SERVICE_HOST}",
+ },
+ port = {
+ type = "string",
+ oneOf = port_patterns,
+ default = "${KUBERNETES_SERVICE_PORT}",
+ },
+ },
+ default = {
+ schema = "https",
+ host = "${KUBERNETES_SERVICE_HOST}",
+ port = "${KUBERNETES_SERVICE_PORT}",
+ }
},
- match = {
- type = "array",
- items = {
- type = "string",
- pattern = namespace_regex_pattern
+ client = {
+ type = "object",
+ properties = {
+ token = token_schema,
+ token_file = token_file_schema,
},
- minItems = 1
+ default = {
+ token_file =
"/var/run/secrets/kubernetes.io/serviceaccount/token"
+ },
+ ["if"] = {
+ ["not"] = {
+ anyOf = {
+ { required = { "token" } },
+ { required = { "token_file" } },
+ }
+ }
+ },
+ ["then"] = {
+ properties = {
+ token_file = {
+ default =
"/var/run/secrets/kubernetes.io/serviceaccount/token"
+ }
+ }
+ }
},
- not_match = {
- type = "array",
- items = {
+ namespace_selector = namespace_selector_schema,
+ label_selector = label_selector_schema,
+ default_weight = default_weight_schema,
+ shared_size = shared_size_schema,
+ },
+ },
+ {
+ type = "array",
+ minItems = 1,
+ items = {
+ type = "object",
+ properties = {
+ id = {
type = "string",
- pattern = namespace_regex_pattern
+ pattern = [[^[a-z0-9]{1,8}$]]
+ },
+ service = {
+ type = "object",
+ properties = {
+ schema = schema_schema,
+ host = {
+ type = "string",
+ oneOf = host_patterns,
+ },
+ port = {
+ type = "string",
+ oneOf = port_patterns,
+ },
+ },
+ required = { "host", "port" }
+ },
+ client = {
+ type = "object",
+ properties = {
+ token = token_schema,
+ token_file = token_file_schema,
+ },
+ oneOf = {
+ { required = { "token" } },
+ { required = { "token_file" } },
+ },
},
- minItems = 1
+ namespace_selector = namespace_selector_schema,
+ label_selector = label_selector_schema,
+ default_weight = default_weight_schema,
+ shared_size = shared_size_schema,
},
+ required = { "id", "service", "client" }
},
- oneOf = {
- { required = { } },
- { required = { "equal" } },
- { required = { "not_equal" } },
- { required = { "match" } },
- { required = { "not_match" } }
- },
- },
- label_selector = {
- type = "string",
}
- },
- default = {
- service = {
- schema = "https",
- host = "${KUBERNETES_SERVICE_HOST}",
- port = "${KUBERNETES_SERVICE_PORT}",
- },
- client = {
- token_file = "/var/run/secrets/kubernetes.io/serviceaccount/token"
- },
- default_weight = 50
}
}
diff --git a/t/APISIX.pm b/t/APISIX.pm
index 0e5d8b5e3..b6e90b45d 100644
--- a/t/APISIX.pm
+++ b/t/APISIX.pm
@@ -523,6 +523,8 @@ _EOC_
lua_shared_dict etcd-cluster-health-check 10m; # etcd health check
lua_shared_dict ext-plugin 1m;
lua_shared_dict kubernetes 1m;
+ lua_shared_dict kubernetes-first 1m;
+ lua_shared_dict kubernetes-second 1m;
lua_shared_dict tars 1m;
lua_shared_dict xds-config 1m;
lua_shared_dict xds-config-version 1m;
diff --git a/t/cli/test_kubernetes.sh b/t/cli/test_kubernetes.sh
index bc371ee01..f60f856b5 100755
--- a/t/cli/test_kubernetes.sh
+++ b/t/cli/test_kubernetes.sh
@@ -26,23 +26,88 @@ discovery:
host: ${HOST_ENV}
client:
token: ${TOKEN_ENV}
-' > conf/config.yaml
+' >conf/config.yaml
make init
if ! grep "env HOST_ENV" conf/nginx.conf; then
- echo "kubernetes discovery env inject failed"
- exit 1
+ echo "kubernetes discovery env inject failed"
+ exit 1
fi
if ! grep "env KUBERNETES_SERVICE_PORT" conf/nginx.conf; then
- echo "kubernetes discovery env inject failed"
- exit 1
+ echo "kubernetes discovery env inject failed"
+ exit 1
fi
if ! grep "env TOKEN_ENV" conf/nginx.conf; then
- echo "kubernetes discovery env inject failed"
- exit 1
+ echo "kubernetes discovery env inject failed"
+ exit 1
fi
-echo "kubernetes discovery env inject success"
+if ! grep "lua_shared_dict kubernetes 1m;" conf/nginx.conf; then
+ echo "kubernetes discovery lua_shared_dict inject failed"
+ exit 1
+fi
+
+echo '
+discovery:
+ kubernetes:
+ - id: dev
+ service:
+ host: ${DEV_HOST}
+ port: ${DEV_PORT}
+ client:
+ token: ${DEV_TOKEN}
+ - id: pro
+ service:
+ host: ${PRO_HOST}
+ port: ${PRO_PORT}
+ client:
+ token: ${PRO_TOKEN}
+ shared_size: 2m
+' >conf/config.yaml
+
+make init
+
+if ! grep "env DEV_HOST" conf/nginx.conf; then
+ echo "kubernetes discovery env inject failed"
+ exit 1
+fi
+
+if ! grep "env DEV_PORT" conf/nginx.conf; then
+ echo "kubernetes discovery env inject failed"
+ exit 1
+fi
+
+if ! grep "env DEV_TOKEN" conf/nginx.conf; then
+ echo "kubernetes discovery env inject failed"
+ exit 1
+fi
+
+if ! grep "env PRO_HOST" conf/nginx.conf; then
+ echo "kubernetes discovery env inject failed"
+ exit 1
+fi
+
+if ! grep "env PRO_PORT" conf/nginx.conf; then
+ echo "kubernetes discovery env inject failed"
+ exit 1
+fi
+
+if ! grep "env PRO_TOKEN" conf/nginx.conf; then
+ echo "kubernetes discovery env inject failed"
+ exit 1
+fi
+
+if ! grep "lua_shared_dict kubernetes-dev 1m;" conf/nginx.conf; then
+ echo "kubernetes discovery lua_shared_dict inject failed"
+ exit 1
+fi
+
+if ! grep "lua_shared_dict kubernetes-pro 2m;" conf/nginx.conf; then
+ echo "kubernetes discovery lua_shared_dict inject failed"
+ exit 1
+fi
+
+echo "kubernetes discovery inject success"
diff --git a/t/kubernetes/discovery/kubernetes.t
b/t/kubernetes/discovery/kubernetes.t
index 4a7b8573b..a631cc98a 100644
--- a/t/kubernetes/discovery/kubernetes.t
+++ b/t/kubernetes/discovery/kubernetes.t
@@ -14,74 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-BEGIN {
- my $token_var_file = "/var/run/secrets/kubernetes.io/serviceaccount/token";
- my $token_from_var = eval {`cat $token_var_file 2>/dev/null`};
- if ($token_from_var) {
-
- our $yaml_config = <<_EOC_;
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes: {}
-_EOC_
- our $token_file = $token_var_file;
- our $token_value = $token_from_var;
-
- }
-
- my $token_tmp_file =
"/tmp/var/run/secrets/kubernetes.io/serviceaccount/token";
- my $token_from_tmp = eval {`cat $token_tmp_file 2>/dev/null`};
- if ($token_from_tmp) {
-
- our $yaml_config = <<_EOC_;
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- client:
- token_file: /tmp/var/run/secrets/kubernetes.io/serviceaccount/token
-_EOC_
- our $token_file = $token_tmp_file;
- our $token_value = $token_from_tmp;
- }
-
- our $scale_ns_c = <<_EOC_;
-[
- {
- "op": "replace_subsets",
- "name": "ep",
- "namespace": "ns-c",
- "subsets": [
- {
- "addresses": [
- {
- "ip": "10.0.0.1"
- }
- ],
- "ports": [
- {
- "name": "p1",
- "port": 5001
- }
- ]
- }
- ]
- }
-]
-_EOC_
-
-}
-
use t::APISIX 'no_plan';
repeat_each(1);
-log_level('debug');
+log_level('warn');
no_root_location();
no_shuffle();
workers(4);
@@ -96,317 +32,96 @@ _EOC_
$block->set_value("apisix_yaml", $apisix_yaml);
- my $main_config = $block->main_config // <<_EOC_;
-env KUBERNETES_SERVICE_HOST=127.0.0.1;
-env KUBERNETES_SERVICE_PORT=6443;
-env KUBERNETES_CLIENT_TOKEN=$::token_value;
-env KUBERNETES_CLIENT_TOKEN_FILE=$::token_file;
-_EOC_
-
- $block->set_value("main_config", $main_config);
-
my $config = $block->config // <<_EOC_;
- location /queries {
- content_by_lua_block {
- local core = require("apisix.core")
- local d = require("apisix.discovery.kubernetes")
-
- ngx.sleep(1)
-
- ngx.req.read_body()
- local request_body = ngx.req.get_body_data()
- local queries = core.json.decode(request_body)
- local response_body = "{"
- for _,query in ipairs(queries) do
- local nodes = d.nodes(query)
- if nodes==nil or #nodes==0 then
- response_body=response_body.." "..0
- else
- response_body=response_body.." "..#nodes
- end
- end
- ngx.say(response_body.." }")
- }
- }
- location /operators {
+ location /compare {
content_by_lua_block {
local http = require("resty.http")
local core = require("apisix.core")
- local ipairs = ipairs
-
- ngx.req.read_body()
- local request_body = ngx.req.get_body_data()
- local operators = core.json.decode(request_body)
-
- core.log.info("get body ", request_body)
- core.log.info("get operators ", #operators)
- for _, op in ipairs(operators) do
- local method, path, body
- local headers = {
- ["Host"] = "127.0.0.1:6445"
- }
-
- if op.op == "replace_subsets" then
- method = "PATCH"
- path = "/api/v1/namespaces/" .. op.namespace ..
"/endpoints/" .. op.name
- if #op.subsets == 0 then
- body =
'[{"path":"/subsets","op":"replace","value":[]}]'
- else
- local t = { { op = "replace", path = "/subsets",
value = op.subsets } }
- body = core.json.encode(t, true)
+ local local_conf =
require("apisix.core.config_local").local_conf()
+
+ local function deep_compare(tbl1, tbl2)
+ if tbl1 == tbl2 then
+ return true
+ elseif type(tbl1) == "table" and type(tbl2) == "table" then
+ for key1, value1 in pairs(tbl1) do
+ local value2 = tbl2[key1]
+ if value2 == nil then
+ -- avoid the type call for missing keys in
tbl2 by directly comparing with nil
+ return false
+ elseif value1 ~= value2 then
+ if type(value1) == "table" and type(value2) ==
"table" then
+ if not deep_compare(value1, value2) then
+ return false
+ end
+ else
+ return false
+ end
+ end
end
- headers["Content-Type"] = "application/json-patch+json"
+ for key2, _ in pairs(tbl2) do
+ if tbl1[key2] == nil then
+ return false
+ end
+ end
+ return true
end
- if op.op == "replace_labels" then
- method = "PATCH"
- path = "/api/v1/namespaces/" .. op.namespace ..
"/endpoints/" .. op.name
- local t = { { op = "replace", path =
"/metadata/labels", value = op.labels } }
- body = core.json.encode(t, true)
- headers["Content-Type"] = "application/json-patch+json"
- end
+ return false
+ end
- local httpc = http.new()
- core.log.info("begin to connect ", "127.0.0.1:6445")
- local ok, message = httpc:connect({
- scheme = "http",
- host = "127.0.0.1",
- port = 6445,
- })
- if not ok then
- core.log.error("connect 127.0.0.1:6445 failed, message
: ", message)
- ngx.say("FAILED")
- end
- local res, err = httpc:request({
- method = method,
- path = path,
- headers = headers,
- body = body,
- })
- if err ~= nil then
- core.log.err("operator k8s cluster error: ", err)
- return 500
- end
- if res.status ~= 200 and res.status ~= 201 and res.status
~= 409 then
- return res.status
- end
+ ngx.req.read_body()
+ local request_body = ngx.req.get_body_data()
+ local expect = core.json.decode(request_body)
+ local current = local_conf.discovery.kubernetes
+ if deep_compare(expect,current) then
+ ngx.say("true")
+ else
+ ngx.say("false, current is ",core.json.encode(current,true))
end
- ngx.say("DONE")
}
}
_EOC_
$block->set_value("config", $config);
+
});
run_tests();
__DATA__
-=== TEST 1: create namespace and endpoints
---- yaml_config eval: $::yaml_config
---- request
-POST /operators
-[
- {
- "op": "replace_subsets",
- "namespace": "ns-a",
- "name": "ep",
- "subsets": [
- {
- "addresses": [
- {
- "ip": "10.0.0.1"
- },
- {
- "ip": "10.0.0.2"
- }
- ],
- "ports": [
- {
- "name": "p1",
- "port": 5001
- }
- ]
- },
- {
- "addresses": [
- {
- "ip": "20.0.0.1"
- },
- {
- "ip": "20.0.0.2"
- }
- ],
- "ports": [
- {
- "name": "p2",
- "port": 5002
- }
- ]
- }
- ]
- },
- {
- "op": "create_namespace",
- "name": "ns-b"
- },
- {
- "op": "replace_subsets",
- "namespace": "ns-b",
- "name": "ep",
- "subsets": [
- {
- "addresses": [
- {
- "ip": "10.0.0.1"
- },
- {
- "ip": "10.0.0.2"
- }
- ],
- "ports": [
- {
- "name": "p1",
- "port": 5001
- }
- ]
- },
- {
- "addresses": [
- {
- "ip": "20.0.0.1"
- },
- {
- "ip": "20.0.0.2"
- }
- ],
- "ports": [
- {
- "name": "p2",
- "port": 5002
- }
- ]
- }
- ]
- },
- {
- "op": "create_namespace",
- "name": "ns-c"
- },
- {
- "op": "replace_subsets",
- "namespace": "ns-c",
- "name": "ep",
- "subsets": [
- {
- "addresses": [
- {
- "ip": "10.0.0.1"
- },
- {
- "ip": "10.0.0.2"
- }
- ],
- "ports": [
- {
- "port": 5001
- }
- ]
- },
- {
- "addresses": [
- {
- "ip": "20.0.0.1"
- },
- {
- "ip": "20.0.0.2"
- }
- ],
- "ports": [
- {
- "port": 5002
- }
- ]
- }
- ]
- }
-]
---- more_headers
-Content-type: application/json
---- error_code: 200
---- no_error_log
-[error]
-
-
-
-=== TEST 2: use default parameters
---- yaml_config eval: $::yaml_config
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 3: use specify parameters
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- host: "127.0.0.1"
- port: "6443"
- client:
- token: "${KUBERNETES_CLIENT_TOKEN}"
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 4: use specify environment parameters
+=== TEST 1: default value with minimal configuration
--- yaml_config
apisix:
node_listen: 1984
config_center: yaml
enable_admin: false
discovery:
- kubernetes:
- service:
- host: ${KUBERNETES_SERVICE_HOST}
- port: ${KUBERNETES_SERVICE_PORT}
- client:
- token: ${KUBERNETES_CLIENT_TOKEN}
+ kubernetes: {}
--- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+GET /compare
+{
+ "service": {
+ "schema": "https",
+ "host": "${KUBERNETES_SERVICE_HOST}",
+ "port": "${KUBERNETES_SERVICE_PORT}"
+ },
+ "client": {
+ "token_file": "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ },
+ "shared_size": "1m",
+ "default_weight": 50
+}
--- more_headers
Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
+--- response_body
+true
-=== TEST 5: use token_file
+=== TEST 2: default value with minimal service and client configuration
--- yaml_config
apisix:
node_listen: 1984
@@ -414,21 +129,30 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ service: {}
+ client: {}
--- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+GET /compare
+{
+ "service": {
+ "schema": "https",
+ "host": "${KUBERNETES_SERVICE_HOST}",
+ "port": "${KUBERNETES_SERVICE_PORT}"
+ },
+ "client": {
+ "token_file": "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ },
+ "shared_size": "1m",
+ "default_weight": 50
+}
--- more_headers
Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
+--- response_body
+true
-=== TEST 6: use http
+=== TEST 3: mixing set custom and default values
--- yaml_config
apisix:
node_listen: 1984
@@ -437,96 +161,30 @@ apisix:
discovery:
kubernetes:
service:
- schema: http
- host: "127.0.0.1"
- port: "6445"
- client:
- token: ""
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 7: use namespace selector equal
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- equal: ns-a
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 0 0 0 0 }
---- no_error_log
-[error]
-
-
-
-=== TEST 8: use namespace selector not_equal
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_equal: ns-a
+ host: "sample.com"
+ shared_size: "2m"
--- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 0 0 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 9: use namespace selector match
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- match: [ns-a,ns-b]
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+GET /compare
+{
+ "service": {
+ "schema": "https",
+ "host": "sample.com",
+ "port": "${KUBERNETES_SERVICE_PORT}"
+ },
+ "client": {
+ "token_file" : "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ },
+ "shared_size": "2m",
+ "default_weight": 50
+}
--- more_headers
Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 0 0 }
---- no_error_log
-[error]
+--- response_body
+true
-=== TEST 10: use namespace selector match with regex
+=== TEST 4: mixing set custom and default values
--- yaml_config
apisix:
node_listen: 1984
@@ -534,23 +192,33 @@ apisix:
enable_admin: false
discovery:
kubernetes:
+ service:
+ schema: "http"
client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- match: ["ns-[ab]"]
+ token: "test"
+ default_weight: 33
--- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+GET /compare
+{
+ "service": {
+ "schema": "http",
+ "host": "${KUBERNETES_SERVICE_HOST}",
+ "port": "${KUBERNETES_SERVICE_PORT}"
+ },
+ "client": {
+ "token": "test"
+ },
+ "shared_size": "1m",
+ "default_weight": 33
+}
--- more_headers
Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 0 0 }
---- no_error_log
-[error]
+--- response_body
+true
-=== TEST 11: use namespace selector not_match
+=== TEST 5: multi cluster mode configuration
--- yaml_config
apisix:
node_listen: 1984
@@ -558,157 +226,52 @@ apisix:
enable_admin: false
discovery:
kubernetes:
+ - id: "debug"
+ service:
+ host: "1.cluster.com"
+ port: "6445"
client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_match: ["ns-a"]
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 0 0 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 12: use namespace selector not_match with regex
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
+ token: "token"
+ - id: "release"
+ service:
+ schema: "http"
+ host: "2.cluster.com"
+ port: "${MyPort}"
client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_match: ["ns-[ab]"]
+ token_file: "/var/token"
+ default_weight: 33
+ shared_size: "2m"
--- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 0 0 0 0 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 13: use label selector
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- label_selector: |-
- first=1,second
---- request eval
-[
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"labels\":{}}]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-b\",\"labels\":{}}]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{}}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"labels\":{\"first\":\"1\"
}}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-b\",\"labels\":{\"first\":\"1\",\"second\":\"o\"
}}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"2\",\"second\":\"o\"
}}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"1\"
}}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
-
-"POST /operators
-[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"1\",\"second\":\"o\"
}}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
-
-]
---- response_body eval
+GET /compare
[
- "DONE\n",
- "DONE\n",
- "DONE\n",
- "{ 0 0 0 }\n",
- "DONE\n",
- "{ 0 0 0 }\n",
- "DONE\n",
- "{ 0 2 0 }\n",
- "DONE\n",
- "{ 0 2 0 }\n",
- "DONE\n",
- "{ 0 2 0 }\n",
- "DONE\n",
- "{ 0 2 2 }\n",
-]
---- no_error_log
-[error]
-
-
-
-=== TEST 14: scale endpoints
---- yaml_config eval: $::yaml_config
---- request eval
-[
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-a/ep:p2\"]",
-
-"POST /operators
-[{\"op\":\"replace_subsets\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"subsets\":[]}]",
-
-"GET /queries
-[\"ns-a/ep:p1\",\"ns-a/ep:p2\"]",
-
-"GET /queries
-[\"ns-c/ep:5001\",\"ns-c/ep:5002\",\"ns-c/ep:p1\"]",
-
-"POST /operators
-$::scale_ns_c",
-
-"GET /queries
-[\"ns-c/ep:5001\",\"ns-c/ep:5002\",\"ns-c/ep:p1\"]",
-
-]
---- response_body eval
-[
- "{ 2 2 }\n",
- "DONE\n",
- "{ 0 0 }\n",
- "{ 2 2 0 }\n",
- "DONE\n",
- "{ 0 0 1 }\n",
+ {
+ "id": "debug",
+ "service": {
+ "schema": "https",
+ "host": "1.cluster.com",
+ "port": "6445"
+ },
+ "client": {
+ "token": "token"
+ },
+ "default_weight": 50,
+ "shared_size": "1m"
+ },
+ {
+ "id": "release",
+ "service": {
+ "schema": "http",
+ "host": "2.cluster.com",
+ "port": "${MyPort}"
+ },
+ "client": {
+ "token_file": "/var/token"
+ },
+ "default_weight": 33,
+ "shared_size": "2m"
+ }
]
---- no_error_log
-[error]
+--- more_headers
+Content-type: application/json
+--- response_body
+true
diff --git a/t/kubernetes/discovery/kubernetes.t
b/t/kubernetes/discovery/kubernetes2.t
similarity index 60%
copy from t/kubernetes/discovery/kubernetes.t
copy to t/kubernetes/discovery/kubernetes2.t
index 4a7b8573b..8a71cd8cd 100644
--- a/t/kubernetes/discovery/kubernetes.t
+++ b/t/kubernetes/discovery/kubernetes2.t
@@ -16,40 +16,31 @@
#
BEGIN {
- my $token_var_file = "/var/run/secrets/kubernetes.io/serviceaccount/token";
- my $token_from_var = eval {`cat $token_var_file 2>/dev/null`};
- if ($token_from_var) {
+ our $token_file =
"/tmp/var/run/secrets/kubernetes.io/serviceaccount/token";
+ our $token_value = eval {`cat $token_file 2>/dev/null`};
- our $yaml_config = <<_EOC_;
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes: {}
-_EOC_
- our $token_file = $token_var_file;
- our $token_value = $token_from_var;
-
- }
-
- my $token_tmp_file =
"/tmp/var/run/secrets/kubernetes.io/serviceaccount/token";
- my $token_from_tmp = eval {`cat $token_tmp_file 2>/dev/null`};
- if ($token_from_tmp) {
-
- our $yaml_config = <<_EOC_;
+ our $yaml_config = <<_EOC_;
apisix:
node_listen: 1984
config_center: yaml
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: /tmp/var/run/secrets/kubernetes.io/serviceaccount/token
+ - id: first
+ service:
+ host: "127.0.0.1"
+ port: "6443"
+ client:
+ token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+
_EOC_
- our $token_file = $token_tmp_file;
- our $token_value = $token_from_tmp;
- }
our $scale_ns_c = <<_EOC_;
[
@@ -81,7 +72,7 @@ _EOC_
use t::APISIX 'no_plan';
repeat_each(1);
-log_level('debug');
+log_level('warn');
no_root_location();
no_shuffle();
workers(4);
@@ -199,6 +190,11 @@ _EOC_
_EOC_
$block->set_value("config", $config);
+
+ if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
+ $block->set_value("no_error_log", "[error]");
+ }
+
});
run_tests();
@@ -336,9 +332,6 @@ POST /operators
]
--- more_headers
Content-type: application/json
---- error_code: 200
---- no_error_log
-[error]
@@ -346,67 +339,18 @@ Content-type: application/json
--- yaml_config eval: $::yaml_config
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 3: use specify parameters
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- host: "127.0.0.1"
- port: "6443"
- client:
- token: "${KUBERNETES_CLIENT_TOKEN}"
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 4: use specify environment parameters
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- host: ${KUBERNETES_SERVICE_HOST}
- port: ${KUBERNETES_SERVICE_PORT}
- client:
- token: ${KUBERNETES_CLIENT_TOKEN}
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 5: use token_file
+=== TEST 3: use specify environment parameters
--- yaml_config
apisix:
node_listen: 1984
@@ -414,47 +358,34 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
-
-=== TEST 6: use http
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- schema: http
- host: "127.0.0.1"
- port: "6445"
- client:
- token: ""
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 7: use namespace selector equal
+=== TEST 4: use namespace selector equal
--- yaml_config
apisix:
node_listen: 1984
@@ -462,23 +393,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- equal: ns-a
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ equal: ns-a
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 0 0 0 0 }
---- no_error_log
-[error]
+qr{ 2 2 0 0 0 0 2 2 2 2 2 2 }
-=== TEST 8: use namespace selector not_equal
+=== TEST 5: use namespace selector not_equal
--- yaml_config
apisix:
node_listen: 1984
@@ -486,23 +429,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_equal: ns-a
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ not_equal: ns-a
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 0 0 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 0 0 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 9: use namespace selector match
+=== TEST 6: use namespace selector match
--- yaml_config
apisix:
node_listen: 1984
@@ -510,23 +465,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- match: [ns-a,ns-b]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ match: [ns-a,ns-b]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 0 0 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 0 0 2 2 2 2 2 2 }
-=== TEST 10: use namespace selector match with regex
+=== TEST 7: use namespace selector match with regex
--- yaml_config
apisix:
node_listen: 1984
@@ -534,23 +501,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- match: ["ns-[ab]"]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ match: ["ns-[ab]"]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 0 0 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 0 0 2 2 2 2 2 2 }
-=== TEST 11: use namespace selector not_match
+=== TEST 8: use namespace selector not_match
--- yaml_config
apisix:
node_listen: 1984
@@ -558,23 +537,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_match: ["ns-a"]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ not_match: ["ns-a"]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 0 0 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 0 0 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 12: use namespace selector not_match with regex
+=== TEST 9: use namespace selector not_match with regex
--- yaml_config
apisix:
node_listen: 1984
@@ -582,23 +573,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_match: ["ns-[ab]"]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ not_match: ["ns-[ab]"]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 0 0 0 0 2 2 }
---- no_error_log
-[error]
+qr{ 0 0 0 0 2 2 2 2 2 2 2 2 }
-=== TEST 13: use label selector
+=== TEST 10: use label selector
--- yaml_config
apisix:
node_listen: 1984
@@ -606,10 +609,21 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- label_selector: |-
- first=1,second
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ label_selector: |-
+ first=1,second
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request eval
[
@@ -623,37 +637,37 @@ discovery:
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"labels\":{\"first\":\"1\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-b\",\"labels\":{\"first\":\"1\",\"second\":\"o\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"2\",\"second\":\"o\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"1\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"1\",\"second\":\"o\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
]
--- response_body eval
@@ -673,42 +687,51 @@ discovery:
"DONE\n",
"{ 0 2 2 }\n",
]
---- no_error_log
-[error]
-=== TEST 14: scale endpoints
+=== TEST 11: scale endpoints
--- yaml_config eval: $::yaml_config
--- request eval
[
+
"GET /queries
-[\"ns-a/ep:p1\",\"ns-a/ep:p2\"]",
+[
+ \"first/ns-a/ep:p1\",\"first/ns-a/ep:p2\",
+ \"second/ns-a/ep:p1\",\"second/ns-a/ep:p2\"
+]",
"POST /operators
[{\"op\":\"replace_subsets\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"subsets\":[]}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-a/ep:p2\"]",
+[
+ \"first/ns-a/ep:p1\",\"first/ns-a/ep:p2\",
+ \"second/ns-a/ep:p1\",\"second/ns-a/ep:p2\"
+]",
"GET /queries
-[\"ns-c/ep:5001\",\"ns-c/ep:5002\",\"ns-c/ep:p1\"]",
+[
+ \"first/ns-c/ep:5001\",\"first/ns-c/ep:5002\",\"first/ns-c/ep:p1\",
+ \"second/ns-c/ep:5001\",\"second/ns-c/ep:5002\",\"second/ns-c/ep:p1\"
+]",
"POST /operators
$::scale_ns_c",
"GET /queries
-[\"ns-c/ep:5001\",\"ns-c/ep:5002\",\"ns-c/ep:p1\"]",
+[
+ \"first/ns-c/ep:5001\",\"first/ns-c/ep:5002\",\"first/ns-c/ep:p1\",
+ \"second/ns-c/ep:5001\",\"second/ns-c/ep:5002\",\"second/ns-c/ep:p1\"
+]"
]
--- response_body eval
[
- "{ 2 2 }\n",
+ "{ 2 2 2 2 }\n",
"DONE\n",
- "{ 0 0 }\n",
- "{ 2 2 0 }\n",
+ "{ 0 0 0 0 }\n",
+ "{ 2 2 0 2 2 0 }\n",
"DONE\n",
- "{ 0 0 1 }\n",
+ "{ 0 0 1 0 0 1 }\n",
]
---- no_error_log
-[error]
diff --git a/t/kubernetes/discovery/kubernetes.t
b/t/kubernetes/discovery/kubernetes3.t
similarity index 60%
copy from t/kubernetes/discovery/kubernetes.t
copy to t/kubernetes/discovery/kubernetes3.t
index 4a7b8573b..8a71cd8cd 100644
--- a/t/kubernetes/discovery/kubernetes.t
+++ b/t/kubernetes/discovery/kubernetes3.t
@@ -16,40 +16,31 @@
#
BEGIN {
- my $token_var_file = "/var/run/secrets/kubernetes.io/serviceaccount/token";
- my $token_from_var = eval {`cat $token_var_file 2>/dev/null`};
- if ($token_from_var) {
+ our $token_file =
"/tmp/var/run/secrets/kubernetes.io/serviceaccount/token";
+ our $token_value = eval {`cat $token_file 2>/dev/null`};
- our $yaml_config = <<_EOC_;
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes: {}
-_EOC_
- our $token_file = $token_var_file;
- our $token_value = $token_from_var;
-
- }
-
- my $token_tmp_file =
"/tmp/var/run/secrets/kubernetes.io/serviceaccount/token";
- my $token_from_tmp = eval {`cat $token_tmp_file 2>/dev/null`};
- if ($token_from_tmp) {
-
- our $yaml_config = <<_EOC_;
+ our $yaml_config = <<_EOC_;
apisix:
node_listen: 1984
config_center: yaml
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: /tmp/var/run/secrets/kubernetes.io/serviceaccount/token
+ - id: first
+ service:
+ host: "127.0.0.1"
+ port: "6443"
+ client:
+ token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+
_EOC_
- our $token_file = $token_tmp_file;
- our $token_value = $token_from_tmp;
- }
our $scale_ns_c = <<_EOC_;
[
@@ -81,7 +72,7 @@ _EOC_
use t::APISIX 'no_plan';
repeat_each(1);
-log_level('debug');
+log_level('warn');
no_root_location();
no_shuffle();
workers(4);
@@ -199,6 +190,11 @@ _EOC_
_EOC_
$block->set_value("config", $config);
+
+ if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
+ $block->set_value("no_error_log", "[error]");
+ }
+
});
run_tests();
@@ -336,9 +332,6 @@ POST /operators
]
--- more_headers
Content-type: application/json
---- error_code: 200
---- no_error_log
-[error]
@@ -346,67 +339,18 @@ Content-type: application/json
--- yaml_config eval: $::yaml_config
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 3: use specify parameters
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- host: "127.0.0.1"
- port: "6443"
- client:
- token: "${KUBERNETES_CLIENT_TOKEN}"
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
-
-
-=== TEST 4: use specify environment parameters
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- host: ${KUBERNETES_SERVICE_HOST}
- port: ${KUBERNETES_SERVICE_PORT}
- client:
- token: ${KUBERNETES_CLIENT_TOKEN}
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 5: use token_file
+=== TEST 3: use specify environment parameters
--- yaml_config
apisix:
node_listen: 1984
@@ -414,47 +358,34 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
---- request
-GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
---- more_headers
-Content-type: application/json
---- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
-
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
-
-=== TEST 6: use http
---- yaml_config
-apisix:
- node_listen: 1984
- config_center: yaml
- enable_admin: false
-discovery:
- kubernetes:
- service:
- schema: http
- host: "127.0.0.1"
- port: "6445"
- client:
- token: ""
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 7: use namespace selector equal
+=== TEST 4: use namespace selector equal
--- yaml_config
apisix:
node_listen: 1984
@@ -462,23 +393,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- equal: ns-a
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ equal: ns-a
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 0 0 0 0 }
---- no_error_log
-[error]
+qr{ 2 2 0 0 0 0 2 2 2 2 2 2 }
-=== TEST 8: use namespace selector not_equal
+=== TEST 5: use namespace selector not_equal
--- yaml_config
apisix:
node_listen: 1984
@@ -486,23 +429,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_equal: ns-a
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ not_equal: ns-a
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 0 0 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 0 0 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 9: use namespace selector match
+=== TEST 6: use namespace selector match
--- yaml_config
apisix:
node_listen: 1984
@@ -510,23 +465,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- match: [ns-a,ns-b]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ match: [ns-a,ns-b]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 0 0 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 0 0 2 2 2 2 2 2 }
-=== TEST 10: use namespace selector match with regex
+=== TEST 7: use namespace selector match with regex
--- yaml_config
apisix:
node_listen: 1984
@@ -534,23 +501,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- match: ["ns-[ab]"]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ match: ["ns-[ab]"]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 2 2 2 2 0 0 }
---- no_error_log
-[error]
+qr{ 2 2 2 2 0 0 2 2 2 2 2 2 }
-=== TEST 11: use namespace selector not_match
+=== TEST 8: use namespace selector not_match
--- yaml_config
apisix:
node_listen: 1984
@@ -558,23 +537,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_match: ["ns-a"]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ not_match: ["ns-a"]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 0 0 2 2 2 2 }
---- no_error_log
-[error]
+qr{ 0 0 2 2 2 2 2 2 2 2 2 2 }
-=== TEST 12: use namespace selector not_match with regex
+=== TEST 9: use namespace selector not_match with regex
--- yaml_config
apisix:
node_listen: 1984
@@ -582,23 +573,35 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- namespace_selector:
- not_match: ["ns-[ab]"]
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ namespace_selector:
+ not_match: ["ns-[ab]"]
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request
GET /queries
-["ns-a/ep:p1","ns-a/ep:p2","ns-b/ep:p1","ns-b/ep:p2","ns-c/ep:5001","ns-c/ep:5002"]
+[
+
"first/ns-a/ep:p1","first/ns-a/ep:p2","first/ns-b/ep:p1","first/ns-b/ep:p2","first/ns-c/ep:5001","first/ns-c/ep:5002",
+
"second/ns-a/ep:p1","second/ns-a/ep:p2","second/ns-b/ep:p1","second/ns-b/ep:p2","second/ns-c/ep:5001","second/ns-c/ep:5002"
+]
--- more_headers
Content-type: application/json
--- response_body eval
-qr{ 0 0 0 0 2 2 }
---- no_error_log
-[error]
+qr{ 0 0 0 0 2 2 2 2 2 2 2 2 }
-=== TEST 13: use label selector
+=== TEST 10: use label selector
--- yaml_config
apisix:
node_listen: 1984
@@ -606,10 +609,21 @@ apisix:
enable_admin: false
discovery:
kubernetes:
- client:
- token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
- label_selector: |-
- first=1,second
+ - id: first
+ service:
+ host: ${KUBERNETES_SERVICE_HOST}
+ port: ${KUBERNETES_SERVICE_PORT}
+ client:
+ token_file: ${KUBERNETES_CLIENT_TOKEN_FILE}
+ label_selector: |-
+ first=1,second
+ - id: second
+ service:
+ schema: "http",
+ host: "127.0.0.1",
+ port: "6445"
+ client:
+ token: ${KUBERNETES_CLIENT_TOKEN}
--- request eval
[
@@ -623,37 +637,37 @@ discovery:
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"labels\":{\"first\":\"1\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-b\",\"labels\":{\"first\":\"1\",\"second\":\"o\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"2\",\"second\":\"o\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"1\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
"POST /operators
[{\"op\":\"replace_labels\",\"name\":\"ep\",\"namespace\":\"ns-c\",\"labels\":{\"first\":\"1\",\"second\":\"o\"
}}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-b/ep:p1\",\"ns-c/ep:5001\"]",
+[\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]",
]
--- response_body eval
@@ -673,42 +687,51 @@ discovery:
"DONE\n",
"{ 0 2 2 }\n",
]
---- no_error_log
-[error]
-=== TEST 14: scale endpoints
+=== TEST 11: scale endpoints
--- yaml_config eval: $::yaml_config
--- request eval
[
+
"GET /queries
-[\"ns-a/ep:p1\",\"ns-a/ep:p2\"]",
+[
+ \"first/ns-a/ep:p1\",\"first/ns-a/ep:p2\",
+ \"second/ns-a/ep:p1\",\"second/ns-a/ep:p2\"
+]",
"POST /operators
[{\"op\":\"replace_subsets\",\"name\":\"ep\",\"namespace\":\"ns-a\",\"subsets\":[]}]",
"GET /queries
-[\"ns-a/ep:p1\",\"ns-a/ep:p2\"]",
+[
+ \"first/ns-a/ep:p1\",\"first/ns-a/ep:p2\",
+ \"second/ns-a/ep:p1\",\"second/ns-a/ep:p2\"
+]",
"GET /queries
-[\"ns-c/ep:5001\",\"ns-c/ep:5002\",\"ns-c/ep:p1\"]",
+[
+ \"first/ns-c/ep:5001\",\"first/ns-c/ep:5002\",\"first/ns-c/ep:p1\",
+ \"second/ns-c/ep:5001\",\"second/ns-c/ep:5002\",\"second/ns-c/ep:p1\"
+]",
"POST /operators
$::scale_ns_c",
"GET /queries
-[\"ns-c/ep:5001\",\"ns-c/ep:5002\",\"ns-c/ep:p1\"]",
+[
+ \"first/ns-c/ep:5001\",\"first/ns-c/ep:5002\",\"first/ns-c/ep:p1\",
+ \"second/ns-c/ep:5001\",\"second/ns-c/ep:5002\",\"second/ns-c/ep:p1\"
+]"
]
--- response_body eval
[
- "{ 2 2 }\n",
+ "{ 2 2 2 2 }\n",
"DONE\n",
- "{ 0 0 }\n",
- "{ 2 2 0 }\n",
+ "{ 0 0 0 0 }\n",
+ "{ 2 2 0 2 2 0 }\n",
"DONE\n",
- "{ 0 0 1 }\n",
+ "{ 0 0 1 0 0 1 }\n",
]
---- no_error_log
-[error]