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 19 commits
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
7 changes: 6 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
test_dir:
- t/plugin
- t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misc
- t/node t/router t/script t/stream-node t/utils t/wasm
- t/amesh-library t/node t/router t/script t/stream-node t/utils t/wasm
Copy link
Contributor

Choose a reason for hiding this comment

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

What is amesh?

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, use xds


runs-on: ${{ matrix.platform }}
timeout-minutes: 90
Expand Down Expand Up @@ -90,6 +90,11 @@ jobs:
sudo dpkg -i tinygo_${TINYGO_VER}_amd64.deb
cd t/wasm && find . -type f -name "*.go" | xargs -Ip tinygo build -o p.wasm -scheduler=none -target=wasi p

- name: Build Amesh library
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto.

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

run: |
cd t/amesh-library
go build -o libamesh.so -buildmode=c-shared main.go

- name: Linux Before install
run: sudo ./ci/${{ matrix.os_name }}_runner.sh before_install

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

local base = require("resty.core.base")
local config_local = require("apisix.core.config_local")
local table = table
local error = error
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")
local C = ffi.C
local router_config = ngx.shared["router-config"]
Copy link
Member

@spacewander spacewander Mar 20, 2022

Choose a reason for hiding this comment

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

It is not configuration for router, but for route.

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


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


ffi.cdef[[
extern void initial(void* router_zone_ptr);
]]


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
Copy link
Contributor

Choose a reason for hiding this comment

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

Put them to the module level?

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


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

for k, _ in string_gmatch(cpath, "[^;]+") do
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use ngx.re.gmatch?

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

local fpath = string_match(k, "(.*/)")
Copy link
Contributor

Choose a reason for hiding this comment

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

What about ngx.re.match?

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_libamesh(lib_name)
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 library, tried paths: " ..
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
error("can not load Amesh library, tried paths: " ..
error("can not load xds library, tried paths: " ..

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

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])
local router_shd_cdata = ffi.cast("void*", router_zone)
ameshagent.initial(router_shd_cdata)
end



function _M.init_worker()
local lib_name = "libamesh.so"

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

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
104 changes: 104 additions & 0 deletions t/amesh-library/config_xds.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#
# 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-library/?.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);

my $extra_init_by_lua = <<_EOC_;
--
local config_xds = require("apisix.core.config_xds")

local inject = function(mod, name)
local old_f = mod[name]
mod[name] = function (...)
ngx.log(ngx.WARN, "config_xds run ", name)
return { true }
end
end

inject(config_xds, "new")

_EOC_

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

run_tests;

__DATA__

=== TEST 1: load Amesh library so successfully
--- yaml_config
apisix:
node_listen: 1984
config_center: xds
enable_admin: false
--- config
location /t {
content_by_lua_block {
ngx.say("ok")
}
}
--- no_error_log eval
qr/can not load Amesh library/



=== TEST 2: read data form shdict that wirted by Amesh library
--- yaml_config
apisix:
node_listen: 1984
config_center: xds
enable_admin: false
--- config
location /t {
content_by_lua_block {
-- wait for Amesh library sync data
ngx.sleep(1.5)
local core = require("apisix.core")
local value = ngx.shared["router-config"]:get("/apisix/routes/1")
local route_conf, err = core.json.decode(value)
local json_encode = require("toolkit.json").encode
ngx.say(json_encode(route_conf))
}
}
--- response_body
{"create_time":1646972532,"id":"1","priority":0,"status":1,"update_time":1647250524,"upstream":{"hash_on":"vars","nodes":[{"host":"127.0.0.1","port":80,"priority":0,"weight":1}],"pass_host":"pass","scheme":"http","type":"roundrobin"},"uri":"/hello"}
92 changes: 92 additions & 0 deletions t/amesh-library/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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 initial
func initial(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"
}
}`)

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

func write_route(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)),
)
}