t/kubernetes/discovery/kubernetes2.t (157 lines of code) (raw):

# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # BEGIN { 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 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 $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('warn'); no_root_location(); no_shuffle(); workers(4); add_block_preprocessor(sub { my ($block) = @_; my $apisix_yaml = $block->apisix_yaml // <<_EOC_; routes: [] #END _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 { 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) end headers["Content-Type"] = "application/json-patch+json" 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 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 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 === TEST 2: use default parameters --- yaml_config eval: $::yaml_config --- request GET /queries [ "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 2 2 2 2 2 2 } === TEST 3: use specify environment parameters --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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} --- request GET /queries [ "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 2 2 2 2 2 2 } === TEST 4: use namespace selector equal --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 2 2 2 2 2 2 } === TEST 5: use namespace selector not_equal --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 2 2 2 2 2 2 } === TEST 6: use namespace selector match --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 2 2 2 2 2 2 } === TEST 7: use namespace selector match with regex --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 2 2 2 2 2 2 } === TEST 8: use namespace selector not_match --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 2 2 2 2 2 2 } === TEST 9: use namespace selector not_match with regex --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 2 2 2 2 2 2 } === TEST 10: use label selector --- yaml_config apisix: node_listen: 1984 deployment: role: data_plane role_data_plane: config_provider: yaml discovery: kubernetes: - 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 [ "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 [\"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 [\"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 [\"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 [\"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 [\"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 [\"first/ns-a/ep:p1\",\"first/ns-b/ep:p1\",\"first/ns-c/ep:5001\"]", ] --- response_body eval [ "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", ] === TEST 11: scale endpoints --- yaml_config eval: $::yaml_config --- request eval [ "GET /queries [ \"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 [ \"first/ns-a/ep:p1\",\"first/ns-a/ep:p2\", \"second/ns-a/ep:p1\",\"second/ns-a/ep:p2\" ]", "GET /queries [ \"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 [ \"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 2 2 }\n", "DONE\n", "{ 0 0 0 0 }\n", "{ 2 2 0 2 2 0 }\n", "DONE\n", "{ 0 0 1 0 0 1 }\n", ]