Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support reading configuration form xds(mvp) #6614

Merged
merged 33 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
079eefb
feat: support reading configuration form shdict(mvp)
tzssangglass Mar 15, 2022
808bd6e
ci
tzssangglass Mar 15, 2022
5ffd2bf
fix code lint
tzssangglass Mar 15, 2022
815074d
fix code lint
tzssangglass Mar 15, 2022
1ca0254
fix CI
tzssangglass Mar 15, 2022
dd1315e
Merge branch 'master' into cgtf
tzssangglass Mar 15, 2022
6fa5a6b
fix code review
tzssangglass Mar 15, 2022
3123d81
replace amesh mock method
tzssangglass Mar 15, 2022
ede18da
revert amesh initial function
tzssangglass Mar 15, 2022
5b8726f
fix test cases lib name
tzssangglass Mar 15, 2022
d4c8c19
fix CI error
tzssangglass Mar 16, 2022
ed3fa36
fix CI error
tzssangglass Mar 16, 2022
87e97c1
fix CI error
tzssangglass Mar 16, 2022
519a823
fix CI error
tzssangglass Mar 16, 2022
3345a31
revert test cases changed in traffic-split
tzssangglass Mar 16, 2022
a80954b
Merge branch 'master' of https://github.com/apache/apisix into cgtf
tzssangglass Mar 17, 2022
9a4cb1f
fix code review
tzssangglass Mar 17, 2022
62190bc
fix code review
tzssangglass Mar 17, 2022
82fbcdc
revert config.yaml
tzssangglass Mar 17, 2022
b0fa534
resolve code review
tzssangglass Mar 17, 2022
39cca64
rename
tzssangglass Mar 17, 2022
add82f7
rename
tzssangglass Mar 17, 2022
7465395
resolve code review
tzssangglass Mar 17, 2022
3123324
fix CI
tzssangglass Mar 17, 2022
8a2a67d
resolve code review
tzssangglass Mar 17, 2022
f1fee3b
resolve code review
tzssangglass Mar 18, 2022
a9c9ba0
fix CI error
tzssangglass Mar 18, 2022
9b31b34
rename test cases names
tzssangglass Mar 18, 2022
0166d0a
Merge branch 'master' into cgtf
tzssangglass Mar 21, 2022
513c2b3
resolve code review
tzssangglass Mar 21, 2022
57c88d1
resolve code review
tzssangglass Mar 21, 2022
41abb0a
Merge branch 'master' into cgtf
tzssangglass Mar 21, 2022
aee463f
Merge branch 'master' into cgtf
tzssangglass Mar 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apisix/cli/ngx_tpl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ http {
lua_shared_dict ext-plugin {* http.lua_shared_dict["ext-plugin"] *}; # cache for ext-plugin
{% end %}

{% if config_center == "shdict" then %}
lua_shared_dict router-config 10m;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lua_shared_dict router-config 10m;
lua_shared_dict xds-route-config 10m;

would that be better?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

{% end %}

# for custom shared dict
{% if http.custom_lua_shared_dict then %}
{% for cache_key, cache_size in pairs(http.custom_lua_shared_dict) do %}
Expand Down
1 change: 1 addition & 0 deletions apisix/cli/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ Please modify "admin_key" in conf/config.yaml .
end
sys_conf["wasm"] = yaml_conf.wasm

sys_conf["config_center"] = yaml_conf.apisix.config_center
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled in

for k,v in pairs(yaml_conf.apisix) do

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm this


local wrn = sys_conf["worker_rlimit_nofile"]
local wc = sys_conf["event"]["worker_connections"]
Expand Down
2 changes: 1 addition & 1 deletion apisix/cli/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ local config_schema = {
apisix = {
properties = {
config_center = {
enum = {"etcd", "yaml"},
enum = {"etcd", "yaml", "shdict"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enum = {"etcd", "yaml", "shdict"},
enum = {"etcd", "yaml", "xds"},

would be better?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

},
lua_module_hook = {
pattern = "^[a-zA-Z._-]+$",
Expand Down
126 changes: 126 additions & 0 deletions apisix/core/config_shdict.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
--
-- 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.
--

--- Get configuration form ngx.shared.DICT.
--
-- @module core.config_shdict

local base = require("resty.core.base")
local config_local = require("apisix.core.config_local")
local table = table
local is_http = ngx.config.subsystem == "http"
local string = string
local io = io
local package = package
local new_tab = base.new_tab
local ngx_timer_at = ngx.timer.at
local ffi = require 'ffi'
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved
local C = ffi.C
local router_config = ngx.shared["router-config"]

local process
if is_http then
process = require("ngx.process")
end


ffi.cdef[[
extern void CreateMock(void* writeRoute);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change it to standard C style: create_mock

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should call a init() function here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

init() is the name of a reserved function of go, with special meaning, I replaced it with initial()

]]


local _M = {
version = 0.1,
local_conf = config_local.local_conf,
}


-- todo: refactor this function in chash.lua and radixtree.lua
local function load_shared_lib(lib_name)
local string_gmatch = string.gmatch
local string_match = string.match
local io_open = io.open
local io_close = io.close

local cpath = package.cpath
local tried_paths = new_tab(32, 0)
local i = 1

for k, _ in string_gmatch(cpath, "[^;]+") do
local fpath = string_match(k, "(.*/)")
fpath = fpath .. lib_name

local f = io_open(fpath)
if f ~= nil then
io_close(f)
return ffi.load(fpath)
end
tried_paths[i] = fpath
i = i + 1
end

return nil, tried_paths
end


local function load_ameshagent(lib_name)
ngx_timer_at(0, function(premature)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use the timer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

if premature then
return
end

local ameshagent, tried_paths = load_shared_lib(lib_name)

if not ameshagent then
tried_paths[#tried_paths + 1] = 'tried above paths but can not load '
.. lib_name
error("can not load amesh agent, tried paths: " ..
table.concat(tried_paths, '\r\n', 1, #tried_paths))
end

local router_zone = C.ngx_http_lua_ffi_shdict_udata_to_zone(router_config[1])
membphis marked this conversation as resolved.
Show resolved Hide resolved
local router_shd_cdata = ffi.cast("void*", router_zone)
ameshagent.CreateMock(router_shd_cdata)
end)
end



function _M.init_worker()
local lib_name = "libameshagent"
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved

local postfix = ".so"
if ffi.os == "OSX" then
postfix = ".dylib"
end
lib_name = lib_name .. postfix

if process.type() == "privileged agent" then
load_ameshagent(lib_name)
end

return true
end


function _M.new(key, opts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use injection for test?

my $extra_init_by_lua = <<_EOC_;
-- reduce default report interval
local client = require("skywalking.client")
client.backendTimerDelay = 0.5
local sw_tracer = require("skywalking.tracer")
local inject = function(mod, name)
local old_f = mod[name]
mod[name] = function (...)
ngx.log(ngx.WARN, "skywalking run ", name)
return old_f(...)
end
end
inject(sw_tracer, "start")
inject(sw_tracer, "finish")
inject(sw_tracer, "prepareForReport")
_EOC_

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

-- mock for test
return { true }
end


return _M
5 changes: 5 additions & 0 deletions apisix/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ function _M.http_init_worker()
end
require("apisix.balancer").init_worker()
load_balancer = require("apisix.balancer")

if core.config == require("apisix.core.config_shdict") then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may need to unify the term, the shdict is the container, the xds is the way, I think here config_xds will be better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another option, we can use amesh

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@membphis I don't think so, from the point of view of Apache APISIX, what is amesh? Why do we need to care about a commercial product?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, you are right. config_xds is fine

core.config.init_worker()
end

require("apisix.admin.init").init_worker()

require("apisix.timers").init_worker()
Expand Down
3 changes: 2 additions & 1 deletion t/APISIX.pm
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ apisix:
_EOC_
}

my $lua_deps_path = <<_EOC_;
my $lua_deps_path = $block->lua_deps_path // <<_EOC_;
lua_package_path "$apisix_home/?.lua;$apisix_home/?/init.lua;$apisix_home/deps/share/lua/5.1/?/init.lua;$apisix_home/deps/share/lua/5.1/?.lua;$apisix_home/apisix/?.lua;$apisix_home/t/?.lua;;";
lua_package_cpath "$apisix_home/?.so;$apisix_home/deps/lib/lua/5.1/?.so;$apisix_home/deps/lib64/lua/5.1/?.so;;";
_EOC_
Expand Down Expand Up @@ -507,6 +507,7 @@ _EOC_
lua_capture_error_log 1m; # plugin error-log-logger
lua_shared_dict etcd-cluster-health-check 10m; # etcd health check
lua_shared_dict ext-plugin 1m;
lua_shared_dict router-config 1m;

proxy_ssl_name \$upstream_host;
proxy_ssl_server_name on;
Expand Down
84 changes: 84 additions & 0 deletions t/amesh-agent/config_shdict.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#
# 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.
#
use t::APISIX 'no_plan';

use Cwd qw(cwd);
my $apisix_home = $ENV{APISIX_HOME} || cwd();

repeat_each(1);
no_long_string();
no_root_location();
log_level("info");

add_block_preprocessor(sub {
my ($block) = @_;

if (!$block->request) {
$block->set_value("request", "GET /t");
}

if (!$block->no_error_log) {
$block->set_value("no_error_log", "[error]\n[alert]");
}

my $lua_deps_path = $block->lua_deps_path // <<_EOC_;
lua_package_path "$apisix_home/?.lua;$apisix_home/?/init.lua;$apisix_home/deps/share/lua/5.1/?/init.lua;$apisix_home/deps/share/lua/5.1/?.lua;$apisix_home/apisix/?.lua;$apisix_home/t/?.lua;;";
lua_package_cpath "$apisix_home/?.so;$apisix_home/t/amesh-agent/?.so;$apisix_home/deps/lib/lua/5.1/?.so;$apisix_home/deps/lib64/lua/5.1/?.so;;";
_EOC_

$block->set_value("lua_deps_path", $lua_deps_path);
});

run_tests;

__DATA__

=== TEST 1: load amesh agent so successfully
--- yaml_config
apisix:
node_listen: 1984
config_center: shdict
enable_admin: false
--- config
location /t {
content_by_lua_block {
ngx.say("ok")
}
}
--- no_error_log eval
qr/can not load amesh agent/
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved



=== TEST 2: read data form shdict that wirted by amesh agent
--- yaml_config
apisix:
node_listen: 1984
config_center: shdict
enable_admin: false
--- config
location /t {
content_by_lua_block {
-- wait for amesh agent sync data
ngx.sleep(1.5)
local value = ngx.shared["router-config"]:get("/apisix/routes/1")
local json_encode = require("toolkit.json").encode
ngx.say(json_encode(value))
}
}
--- response_body
"{\n\"status\": 1,\n\"update_time\": 1647250524,\n\"create_time\": 1646972532,\n\"uri\": \"/hello\",\n\"priority\": 0,\n\"id\": \"1\",\n\"upstream\": {\n\t\"nodes\": [\n\t\t{\n\t\t\t\"port\": 80,\n\t\t\t\"priority\": 0,\n\t\t\t\"host\": \"127.0.0.1\",\n\t\t\t\"weight\": 1\n\t\t}\n\t],\n\t\"type\": \"roundrobin\",\n\t\"hash_on\": \"vars\",\n\t\"pass_host\": \"pass\",\n\t\"scheme\": \"http\"\n}\n}%!(EXTRA int64=1647326314)"
91 changes: 91 additions & 0 deletions t/amesh-agent/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package main

/*
#cgo LDFLAGS: -shared
#include <stdlib.h>

extern void ngx_http_lua_ffi_shdict_store(void *zone, int op,
const unsigned char *key, size_t key_len,
int value_type,
const unsigned char *str_value_buf, size_t str_value_len,
double num_value, long exptime, int user_flags, char **errmsg,
int *forcible);
*/
import "C"

import (
"fmt"
"time"
"unsafe"
)

func main() {
}

//export CreateMock
func CreateMock(zone unsafe.Pointer) {
time.Sleep(time.Second)
value := fmt.Sprintf(`{
"status": 1,
"update_time": 1647250524,
"create_time": 1646972532,
"uri": "/hello",
"priority": 0,
"id": "1",
"upstream": {
"nodes": [
{
"port": 80,
"priority": 0,
"host": "127.0.0.1",
"weight": 1
}
],
"type": "roundrobin",
"hash_on": "vars",
"pass_host": "pass",
"scheme": "http"
}
}`, time.Now().Unix())

writeShdict(zone, "/apisix/routes/1", value)
}

func writeShdict(zone unsafe.Pointer, key, value string) {
var keyCStr = C.CString(key)
defer C.free(unsafe.Pointer(keyCStr))
var keyLen = C.size_t(len(key))

var valueCStr = C.CString(value)
defer C.free(unsafe.Pointer(valueCStr))
var valueLen = C.size_t(len(value))

errMsgBuf := make([]*C.char, 1)
var forcible = 0

C.ngx_http_lua_ffi_shdict_store(zone, 0x0004,
(*C.uchar)(unsafe.Pointer(keyCStr)), keyLen,
4,
(*C.uchar)(unsafe.Pointer(valueCStr)), valueLen,
0, 0, 0,
(**C.char)(unsafe.Pointer(&errMsgBuf[0])),
(*C.int)(unsafe.Pointer(&forcible)),
)
}